From 75d33878ab75618f169939f9b6941a5c4794336f Mon Sep 17 00:00:00 2001 From: Andrew Trick Date: Thu, 23 Jun 2011 17:52:36 +0000 Subject: cmake+lit: handle ENABLE_ASSERTIONS feature properly. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133725 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/CMakeLists.txt | 6 ++++++ test/Makefile | 2 +- test/lit.site.cfg.in | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 2db58b9..2634f79 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -79,6 +79,12 @@ if(PYTHONINTERP_FOUND) set(ENABLE_SHARED ${LLVM_SHARED_LIBS_ENABLED}) set(SHLIBPATH_VAR ${SHLIBPATH_VAR}) + if(LLVM_ENABLE_ASSERTIONS) + set(ENABLE_ASSERTIONS "1") + else() + set(ENABLE_ASSERTIONS "0") + endif(LLVM_ENABLE_ASSERTIONS) + # lit.site.cfg uses the config-time build mode set(LLVM_BUILD_MODE "${LLVM_BUILD_MODE}") diff --git a/test/Makefile b/test/Makefile index 4e34e72..c0bc36c 100644 --- a/test/Makefile +++ b/test/Makefile @@ -185,7 +185,7 @@ lit.site.cfg: site.exp @$(ECHOPATH) s=@LLVMGCCDIR@=$(LLVMGCCDIR)=g >> lit.tmp @$(ECHOPATH) s=@PYTHON_EXECUTABLE@=python=g >> lit.tmp @$(ECHOPATH) s=@ENABLE_SHARED@=$(ENABLE_SHARED)=g >> lit.tmp - @$(ECHOPATH) s=@LLVM_ENABLE_ASSERTIONS@=$(ENABLE_ASSERTIONS)=g >> lit.tmp + @$(ECHOPATH) s=@ENABLE_ASSERTIONS@=$(ENABLE_ASSERTIONS)=g >> lit.tmp @sed -f lit.tmp $(PROJ_SRC_DIR)/lit.site.cfg.in > $@ @-rm -f lit.tmp diff --git a/test/lit.site.cfg.in b/test/lit.site.cfg.in index 6c33831..fe152ef 100644 --- a/test/lit.site.cfg.in +++ b/test/lit.site.cfg.in @@ -7,7 +7,7 @@ config.llvmgcc_dir = "@LLVMGCCDIR@" config.lit_tools_dir = "@LLVM_LIT_TOOLS_DIR@" config.python_executable = "@PYTHON_EXECUTABLE@" config.enable_shared = @ENABLE_SHARED@ -config.enable_assertions = @LLVM_ENABLE_ASSERTIONS@ +config.enable_assertions = @ENABLE_ASSERTIONS@ # Support substitution of the tools_dir with user parameters. This is # used when we can't determine the tool dir at configuration time. -- cgit v1.1 From ef41ff618f2537539b538e6c7bf471c753391f92 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Thu, 23 Jun 2011 17:54:54 +0000 Subject: Remove TargetOptions.h dependency from X86Subtarget. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133726 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86FastISel.cpp | 4 +++- lib/Target/X86/X86ISelLowering.cpp | 27 +++++++++++++++++++++++-- lib/Target/X86/X86ISelLowering.h | 6 ++++++ lib/Target/X86/X86Subtarget.cpp | 39 +++++-------------------------------- lib/Target/X86/X86Subtarget.h | 6 ++---- lib/Target/X86/X86TargetMachine.cpp | 6 +++++- 6 files changed, 46 insertions(+), 42 deletions(-) diff --git a/lib/Target/X86/X86FastISel.cpp b/lib/Target/X86/X86FastISel.cpp index f1b9972..82f5d3a 100644 --- a/lib/Target/X86/X86FastISel.cpp +++ b/lib/Target/X86/X86FastISel.cpp @@ -15,6 +15,7 @@ #include "X86.h" #include "X86InstrBuilder.h" +#include "X86ISelLowering.h" #include "X86RegisterInfo.h" #include "X86Subtarget.h" #include "X86TargetMachine.h" @@ -1493,7 +1494,8 @@ bool X86FastISel::DoSelectCall(const Instruction *I, const char *MemIntName) { return false; // Fast-isel doesn't know about callee-pop yet. - if (Subtarget->IsCalleePop(isVarArg, CC)) + if (X86::isCalleePop(CC, Subtarget->is64Bit(), isVarArg, + GuaranteedTailCallOpt)) return false; // Check whether the function can return without sret-demotion. diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 6cd03d0..13bef08 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -1898,7 +1898,7 @@ X86TargetLowering::LowerFormalArguments(SDValue Chain, } // Some CCs need callee pop. - if (Subtarget->IsCalleePop(isVarArg, CallConv)) { + if (X86::isCalleePop(CallConv, Is64Bit, isVarArg, GuaranteedTailCallOpt)) { FuncInfo->setBytesToPopOnReturn(StackSize); // Callee pops everything. } else { FuncInfo->setBytesToPopOnReturn(0); // Callee pops nothing. @@ -2383,7 +2383,7 @@ X86TargetLowering::LowerCall(SDValue Chain, SDValue Callee, // Create the CALLSEQ_END node. unsigned NumBytesForCalleeToPush; - if (Subtarget->IsCalleePop(isVarArg, CallConv)) + if (X86::isCalleePop(CallConv, Is64Bit, isVarArg, GuaranteedTailCallOpt)) NumBytesForCalleeToPush = NumBytes; // Callee pops everything else if (!Is64Bit && !IsTailCallConvention(CallConv) && IsStructRet) // If this is a call to a struct-return function, the callee @@ -2876,6 +2876,29 @@ bool X86::isOffsetSuitableForCodeModel(int64_t Offset, CodeModel::Model M, return false; } +/// isCalleePop - Determines whether the callee is required to pop its +/// own arguments. Callee pop is necessary to support tail calls. +bool X86::isCalleePop(CallingConv::ID CallingConv, + bool is64Bit, bool IsVarArg, bool TailCallOpt) { + if (IsVarArg) + return false; + + switch (CallingConv) { + default: + return false; + case CallingConv::X86_StdCall: + return !is64Bit; + case CallingConv::X86_FastCall: + return !is64Bit; + case CallingConv::X86_ThisCall: + return !is64Bit; + case CallingConv::Fast: + return TailCallOpt; + case CallingConv::GHC: + return TailCallOpt; + } +} + /// TranslateX86CC - do a one to one translation of a ISD::CondCode to the X86 /// specific condition code, returning the condition code and the LHS/RHS of the /// comparison to make. diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h index d61a125..cbe2389 100644 --- a/lib/Target/X86/X86ISelLowering.h +++ b/lib/Target/X86/X86ISelLowering.h @@ -466,6 +466,12 @@ namespace llvm { /// fit into displacement field of the instruction. bool isOffsetSuitableForCodeModel(int64_t Offset, CodeModel::Model M, bool hasSymbolicDisplacement = true); + + + /// isCalleePop - Determines whether the callee is required to pop its + /// own arguments. Callee pop is necessary to support tail calls. + bool isCalleePop(CallingConv::ID CallingConv, + bool is64Bit, bool IsVarArg, bool TailCallOpt); } //===--------------------------------------------------------------------===// diff --git a/lib/Target/X86/X86Subtarget.cpp b/lib/Target/X86/X86Subtarget.cpp index 481e821..adcf69a 100644 --- a/lib/Target/X86/X86Subtarget.cpp +++ b/lib/Target/X86/X86Subtarget.cpp @@ -20,7 +20,6 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/Support/Host.h" #include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetOptions.h" #include "llvm/ADT/SmallVector.h" using namespace llvm; @@ -286,7 +285,7 @@ void X86Subtarget::AutoDetectSubtargetFeatures() { } X86Subtarget::X86Subtarget(const std::string &TT, const std::string &FS, - bool is64Bit) + bool is64Bit, unsigned StackAlignOverride) : PICStyle(PICStyles::None) , X86SSELevel(NoMMXSSE) , X863DNowLevel(NoThreeDNow) @@ -308,10 +307,6 @@ X86Subtarget::X86Subtarget(const std::string &TT, const std::string &FS, , TargetTriple(TT) , Is64Bit(is64Bit) { - // default to hard float ABI - if (FloatABIType == FloatABI::Default) - FloatABIType = FloatABI::Hard; - // Determine default and user specified characteristics if (!FS.empty()) { // If feature string is not empty, parse features string. @@ -346,33 +341,9 @@ X86Subtarget::X86Subtarget(const std::string &TT, const std::string &FS, // Stack alignment is 16 bytes on Darwin, FreeBSD, Linux and Solaris (both // 32 and 64 bit) and for all 64-bit targets. - if (isTargetDarwin() || isTargetFreeBSD() || isTargetLinux() || - isTargetSolaris() || Is64Bit) + if (StackAlignOverride) + stackAlignment = StackAlignOverride; + else if (isTargetDarwin() || isTargetFreeBSD() || isTargetLinux() || + isTargetSolaris() || Is64Bit) stackAlignment = 16; - - if (StackAlignment) - stackAlignment = StackAlignment; -} - -/// IsCalleePop - Determines whether the callee is required to pop its -/// own arguments. Callee pop is necessary to support tail calls. -bool X86Subtarget::IsCalleePop(bool IsVarArg, - CallingConv::ID CallingConv) const { - if (IsVarArg) - return false; - - switch (CallingConv) { - default: - return false; - case CallingConv::X86_StdCall: - return !is64Bit(); - case CallingConv::X86_FastCall: - return !is64Bit(); - case CallingConv::X86_ThisCall: - return !is64Bit(); - case CallingConv::Fast: - return GuaranteedTailCallOpt; - case CallingConv::GHC: - return GuaranteedTailCallOpt; - } } diff --git a/lib/Target/X86/X86Subtarget.h b/lib/Target/X86/X86Subtarget.h index 286a798..49bf74b 100644 --- a/lib/Target/X86/X86Subtarget.h +++ b/lib/Target/X86/X86Subtarget.h @@ -117,7 +117,8 @@ public: /// This constructor initializes the data members to match that /// of the specified triple. /// - X86Subtarget(const std::string &TT, const std::string &FS, bool is64Bit); + X86Subtarget(const std::string &TT, const std::string &FS, bool is64Bit, + unsigned StackAlignOverride); /// getStackAlignment - Returns the minimum alignment known to hold of the /// stack frame on entry to the function and which must be maintained by every @@ -248,9 +249,6 @@ public: /// indicating the number of scheduling cycles of backscheduling that /// should be attempted. unsigned getSpecialAddressLatency() const; - - /// IsCalleePop - Test whether a function should pop its own arguments. - bool IsCalleePop(bool isVarArg, CallingConv::ID CallConv) const; }; } // End llvm namespace diff --git a/lib/Target/X86/X86TargetMachine.cpp b/lib/Target/X86/X86TargetMachine.cpp index 7483329..0b85469 100644 --- a/lib/Target/X86/X86TargetMachine.cpp +++ b/lib/Target/X86/X86TargetMachine.cpp @@ -117,7 +117,7 @@ X86_64TargetMachine::X86_64TargetMachine(const Target &T, const std::string &TT, X86TargetMachine::X86TargetMachine(const Target &T, const std::string &TT, const std::string &FS, bool is64Bit) : LLVMTargetMachine(T, TT), - Subtarget(TT, FS, is64Bit), + Subtarget(TT, FS, is64Bit, StackAlignment), FrameLowering(*this, Subtarget), ELFWriterInfo(is64Bit, true) { DefRelocModel = getRelocationModel(); @@ -182,6 +182,10 @@ X86TargetMachine::X86TargetMachine(const Target &T, const std::string &TT, // Finally, if we have "none" as our PIC style, force to static mode. if (Subtarget.getPICStyle() == PICStyles::None) setRelocationModel(Reloc::Static); + + // default to hard float ABI + if (FloatABIType == FloatABI::Default) + FloatABIType = FloatABI::Hard; } //===----------------------------------------------------------------------===// -- cgit v1.1 From 28578e3137c8e2ab1b406480a262cad34c565c37 Mon Sep 17 00:00:00 2001 From: Andrew Trick Date: Thu, 23 Jun 2011 18:00:32 +0000 Subject: cmake+lit: final cleanup related to the recent churn git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133729 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/CMakeLists.txt | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 2634f79..1fc26a0 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -71,6 +71,8 @@ if(PYTHONINTERP_FOUND) MAKE_DIRECTORY(${CMAKE_CURRENT_BINARY_DIR}/Unit) # Configuration-time: See Unit/lit.site.cfg.in + set(LLVM_BUILD_MODE "%(build_mode)s") + set(LLVM_SOURCE_DIR ${LLVM_MAIN_SRC_DIR}) set(LLVM_BINARY_DIR ${LLVM_BINARY_DIR}) set(LLVM_TOOLS_DIR "${LLVM_TOOLS_BINARY_DIR}/%(build_config)s") @@ -85,17 +87,10 @@ if(PYTHONINTERP_FOUND) set(ENABLE_ASSERTIONS "0") endif(LLVM_ENABLE_ASSERTIONS) - # lit.site.cfg uses the config-time build mode - set(LLVM_BUILD_MODE "${LLVM_BUILD_MODE}") - configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg @ONLY) - - # Unit/lit.site.cfg substitutes the runtime build_mode - set(LLVM_BUILD_MODE "%(build_mode)s") - configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/Unit/lit.site.cfg.in ${CMAKE_CURRENT_BINARY_DIR}/Unit/lit.site.cfg -- cgit v1.1 From 67a918486132309f224d152188747ca5e7f224ca Mon Sep 17 00:00:00 2001 From: Justin Holewinski Date: Thu, 23 Jun 2011 18:10:03 +0000 Subject: PTX: Use .param space for parameters in device functions for SM >= 2.0 FIXME: DCE is eliminating the final st.param.x calls, figure out why git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133732 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/PTX/PTXAsmPrinter.cpp | 3 +- lib/Target/PTX/PTXISelDAGToDAG.cpp | 57 ++++++++++++++++++++++++++++------- lib/Target/PTX/PTXISelLowering.cpp | 61 +++++++++++++++++++++++++++----------- lib/Target/PTX/PTXISelLowering.h | 3 +- lib/Target/PTX/PTXInstrInfo.td | 26 ++++++++++++++-- lib/Target/PTX/PTXSubtarget.h | 9 +++++- 6 files changed, 126 insertions(+), 33 deletions(-) diff --git a/lib/Target/PTX/PTXAsmPrinter.cpp b/lib/Target/PTX/PTXAsmPrinter.cpp index b1f7c1e..0b055c2 100644 --- a/lib/Target/PTX/PTXAsmPrinter.cpp +++ b/lib/Target/PTX/PTXAsmPrinter.cpp @@ -417,6 +417,7 @@ void PTXAsmPrinter::EmitFunctionDeclaration() { const PTXMachineFunctionInfo *MFI = MF->getInfo(); const bool isKernel = MFI->isKernel(); + const PTXSubtarget& ST = TM.getSubtarget(); std::string decl = isKernel ? ".entry" : ".func"; @@ -452,7 +453,7 @@ void PTXAsmPrinter::EmitFunctionDeclaration() { if (i != b) { decl += ", "; } - if (isKernel) { + if (isKernel || ST.getShaderModel() >= PTXSubtarget::PTX_SM_2_0) { decl += ".param .b"; decl += utostr(*i); decl += " "; diff --git a/lib/Target/PTX/PTXISelDAGToDAG.cpp b/lib/Target/PTX/PTXISelDAGToDAG.cpp index b3c85da..1cae8f3 100644 --- a/lib/Target/PTX/PTXISelDAGToDAG.cpp +++ b/lib/Target/PTX/PTXISelDAGToDAG.cpp @@ -15,6 +15,7 @@ #include "PTXTargetMachine.h" #include "llvm/CodeGen/SelectionDAGISel.h" #include "llvm/DerivedTypes.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; @@ -42,7 +43,8 @@ class PTXDAGToDAGISel : public SelectionDAGISel { private: SDNode *SelectREAD_PARAM(SDNode *Node); - + //SDNode *SelectSTORE_PARAM(SDNode *Node); + // We need this only because we can't match intruction BRAdp // pattern (PTXbrcond bb:$d, ...) in PTXInstrInfo.td SDNode *SelectBRCOND(SDNode *Node); @@ -69,6 +71,8 @@ SDNode *PTXDAGToDAGISel::Select(SDNode *Node) { switch (Node->getOpcode()) { case PTXISD::READ_PARAM: return SelectREAD_PARAM(Node); + // case PTXISD::STORE_PARAM: + // return SelectSTORE_PARAM(Node); case ISD::BRCOND: return SelectBRCOND(Node); default: @@ -86,20 +90,15 @@ SDNode *PTXDAGToDAGISel::SelectREAD_PARAM(SDNode *Node) { if (Node->getValueType(0) == MVT::i16) { opcode = PTX::LDpiU16; - } - else if (Node->getValueType(0) == MVT::i32) { + } else if (Node->getValueType(0) == MVT::i32) { opcode = PTX::LDpiU32; - } - else if (Node->getValueType(0) == MVT::i64) { + } else if (Node->getValueType(0) == MVT::i64) { opcode = PTX::LDpiU64; - } - else if (Node->getValueType(0) == MVT::f32) { + } else if (Node->getValueType(0) == MVT::f32) { opcode = PTX::LDpiF32; - } - else if (Node->getValueType(0) == MVT::f64) { + } else if (Node->getValueType(0) == MVT::f64) { opcode = PTX::LDpiF64; - } - else { + } else { llvm_unreachable("Unknown parameter type for ld.param"); } @@ -107,6 +106,42 @@ SDNode *PTXDAGToDAGISel::SelectREAD_PARAM(SDNode *Node) { GetPTXMachineNode(CurDAG, opcode, dl, Node->getValueType(0), index); } +// SDNode *PTXDAGToDAGISel::SelectSTORE_PARAM(SDNode *Node) { +// SDValue Chain = Node->getOperand(0); +// SDValue index = Node->getOperand(1); +// SDValue value = Node->getOperand(2); +// DebugLoc dl = Node->getDebugLoc(); +// unsigned opcode; + +// if (index.getOpcode() != ISD::TargetConstant) +// llvm_unreachable("STORE_PARAM: index is not ISD::TargetConstant"); + +// if (value->getValueType(0) == MVT::i16) { +// opcode = PTX::STpiU16; +// } else if (value->getValueType(0) == MVT::i32) { +// opcode = PTX::STpiU32; +// } else if (value->getValueType(0) == MVT::i64) { +// opcode = PTX::STpiU64; +// } else if (value->getValueType(0) == MVT::f32) { +// opcode = PTX::STpiF32; +// } else if (value->getValueType(0) == MVT::f64) { +// opcode = PTX::STpiF64; +// } else { +// llvm_unreachable("Unknown parameter type for st.param"); +// } + +// SDVTList VTs = CurDAG->getVTList(MVT::Other, MVT::Glue); +// SDValue PredReg = CurDAG->getRegister(PTX::NoRegister, MVT::i1); +// SDValue PredOp = CurDAG->getTargetConstant(PTX::PRED_NORMAL, MVT::i32); +// SDValue Ops[] = { Chain, index, value, PredReg, PredOp }; +// //SDNode *RetNode = PTXInstrInfo:: +// // GetPTXMachineNode(CurDAG, opcode, dl, VTs, index, value); +// SDNode *RetNode = CurDAG->getMachineNode(opcode, dl, VTs, Ops, array_lengthof(Ops)); +// DEBUG(dbgs() << "SelectSTORE_PARAM: Selected: "); +// RetNode->dumpr(CurDAG); +// return RetNode; +// } + SDNode *PTXDAGToDAGISel::SelectBRCOND(SDNode *Node) { assert(Node->getNumOperands() >= 3); diff --git a/lib/Target/PTX/PTXISelLowering.cpp b/lib/Target/PTX/PTXISelLowering.cpp index c3cdaba..782d916 100644 --- a/lib/Target/PTX/PTXISelLowering.cpp +++ b/lib/Target/PTX/PTXISelLowering.cpp @@ -15,6 +15,7 @@ #include "PTXISelLowering.h" #include "PTXMachineFunctionInfo.h" #include "PTXRegisterInfo.h" +#include "PTXSubtarget.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/MachineFunction.h" @@ -106,6 +107,8 @@ const char *PTXTargetLowering::getTargetNodeName(unsigned Opcode) const { return "PTXISD::COPY_ADDRESS"; case PTXISD::READ_PARAM: return "PTXISD::READ_PARAM"; + case PTXISD::STORE_PARAM: + return "PTXISD::STORE_PARAM"; case PTXISD::EXIT: return "PTXISD::EXIT"; case PTXISD::RET: @@ -192,6 +195,7 @@ SDValue PTXTargetLowering:: if (isVarArg) llvm_unreachable("PTX does not support varargs"); MachineFunction &MF = DAG.getMachineFunction(); + const PTXSubtarget& ST = getTargetMachine().getSubtarget(); PTXMachineFunctionInfo *MFI = MF.getInfo(); switch (CallConv) { @@ -206,11 +210,16 @@ SDValue PTXTargetLowering:: break; } - if (MFI->isKernel()) { - // For kernel functions, we just need to emit the proper READ_PARAM ISDs + // We do one of two things here: + // IsKernel || SM >= 2.0 -> Use param space for arguments + // SM < 2.0 -> Use registers for arguments + + if (MFI->isKernel() || ST.getShaderModel() >= PTXSubtarget::PTX_SM_2_0) { + // We just need to emit the proper READ_PARAM ISDs for (unsigned i = 0, e = Ins.size(); i != e; ++i) { - assert(Ins[i].VT != MVT::i1 && "Kernels cannot take pred operands"); + assert((!MFI->isKernel() || Ins[i].VT != MVT::i1) && + "Kernels cannot take pred operands"); SDValue ArgValue = DAG.getNode(PTXISD::READ_PARAM, dl, Ins[i].VT, Chain, DAG.getTargetConstant(i, MVT::i32)); @@ -299,31 +308,49 @@ SDValue PTXTargetLowering:: MachineFunction& MF = DAG.getMachineFunction(); PTXMachineFunctionInfo *MFI = MF.getInfo(); - SmallVector RVLocs; - CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), - getTargetMachine(), RVLocs, *DAG.getContext()); + const PTXSubtarget& ST = getTargetMachine().getSubtarget(); SDValue Flag; - CCInfo.AnalyzeReturn(Outs, RetCC_PTX); + if (ST.getShaderModel() >= PTXSubtarget::PTX_SM_2_0) { + // For SM 2.0+, we return arguments in the param space + for (unsigned i = 0, e = Outs.size(); i != e; ++i) { + SDVTList VTs = DAG.getVTList(MVT::Other, MVT::Glue); + SDValue ParamIndex = DAG.getTargetConstant(i, MVT::i32); + SDValue Ops[] = { Chain, ParamIndex, OutVals[i], Flag }; + Chain = DAG.getNode(PTXISD::STORE_PARAM, dl, VTs, Ops, + Flag.getNode() ? 4 : 3); + Flag = Chain.getValue(1); + // Instead of storing a physical register in our argument list, we just + // store the total size of the parameter, in bits. The ASM printer + // knows how to process this. + MFI->addRetReg(Outs[i].VT.getStoreSizeInBits()); + } + } else { + // For SM < 2.0, we return arguments in registers + SmallVector RVLocs; + CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), + getTargetMachine(), RVLocs, *DAG.getContext()); - for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) { + CCInfo.AnalyzeReturn(Outs, RetCC_PTX); - CCValAssign& VA = RVLocs[i]; + for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) { + CCValAssign& VA = RVLocs[i]; - assert(VA.isRegLoc() && "CCValAssign must be RegLoc"); + assert(VA.isRegLoc() && "CCValAssign must be RegLoc"); - unsigned Reg = VA.getLocReg(); + unsigned Reg = VA.getLocReg(); - DAG.getMachineFunction().getRegInfo().addLiveOut(Reg); + DAG.getMachineFunction().getRegInfo().addLiveOut(Reg); - Chain = DAG.getCopyToReg(Chain, dl, Reg, OutVals[i], Flag); + Chain = DAG.getCopyToReg(Chain, dl, Reg, OutVals[i], Flag); - // Guarantee that all emitted copies are stuck together, - // avoiding something bad - Flag = Chain.getValue(1); + // Guarantee that all emitted copies are stuck together, + // avoiding something bad + Flag = Chain.getValue(1); - MFI->addRetReg(Reg); + MFI->addRetReg(Reg); + } } if (Flag.getNode() == 0) { diff --git a/lib/Target/PTX/PTXISelLowering.h b/lib/Target/PTX/PTXISelLowering.h index ead17ed..e33c0bd 100644 --- a/lib/Target/PTX/PTXISelLowering.h +++ b/lib/Target/PTX/PTXISelLowering.h @@ -25,11 +25,12 @@ namespace PTXISD { enum NodeType { FIRST_NUMBER = ISD::BUILTIN_OP_END, READ_PARAM, + STORE_PARAM, EXIT, RET, COPY_ADDRESS }; -} // namespace PTXISD +} // namespace PTXISD class PTXTargetLowering : public TargetLowering { public: diff --git a/lib/Target/PTX/PTXInstrInfo.td b/lib/Target/PTX/PTXInstrInfo.td index cc74944..b5597d4 100644 --- a/lib/Target/PTX/PTXInstrInfo.td +++ b/lib/Target/PTX/PTXInstrInfo.td @@ -180,10 +180,15 @@ def PTXsra : SDNode<"ISD::SRA", SDTIntBinOp>; def PTXexit : SDNode<"PTXISD::EXIT", SDTNone, [SDNPHasChain]>; def PTXret - : SDNode<"PTXISD::RET", SDTNone, [SDNPHasChain]>; + : SDNode<"PTXISD::RET", SDTNone, + [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; def PTXcopyaddress : SDNode<"PTXISD::COPY_ADDRESS", SDTypeProfile<1, 1, []>, []>; +def PTXstoreparam + : SDNode<"PTXISD::STORE_PARAM", SDTypeProfile<0, 2, [SDTCisVT<0, i32>]>, + [SDNPHasChain, SDNPOutGlue, SDNPOptInGlue]>; + //===----------------------------------------------------------------------===// // Instruction Class Templates //===----------------------------------------------------------------------===// @@ -816,7 +821,7 @@ defm LDc : PTX_LD_ALL<"ld.const", load_constant>; defm LDl : PTX_LD_ALL<"ld.local", load_local>; defm LDs : PTX_LD_ALL<"ld.shared", load_shared>; -// This is a special instruction that is manually inserted for kernel parameters +// This is a special instruction that is manually inserted for parameters def LDpiU16 : InstPTX<(outs RegI16:$d), (ins MEMpi:$a), "ld.param.u16\t$d, [$a]", []>; def LDpiU32 : InstPTX<(outs RegI32:$d), (ins MEMpi:$a), @@ -828,6 +833,23 @@ def LDpiF32 : InstPTX<(outs RegF32:$d), (ins MEMpi:$a), def LDpiF64 : InstPTX<(outs RegF64:$d), (ins MEMpi:$a), "ld.param.f64\t$d, [$a]", []>; +// def STpiPred : InstPTX<(outs), (ins i1imm:$d, RegPred:$a), +// "st.param.pred\t[$d], $a", +// [(PTXstoreparam imm:$d, RegPred:$a)]>; +// def STpiU16 : InstPTX<(outs), (ins i16imm:$d, RegI16:$a), +// "st.param.u16\t[$d], $a", +// [(PTXstoreparam imm:$d, RegI16:$a)]>; +def STpiU32 : InstPTX<(outs), (ins i32imm:$d, RegI32:$a), + "st.param.u32\t[$d], $a", + [(PTXstoreparam timm:$d, RegI32:$a)]>; +// def STpiU64 : InstPTX<(outs), (ins i64imm:$d, RegI64:$a), +// "st.param.u64\t[$d], $a", +// [(PTXstoreparam imm:$d, RegI64:$a)]>; +// def STpiF32 : InstPTX<(outs), (ins MEMpi:$d, RegF32:$a), +// "st.param.f32\t[$d], $a", []>; +// def STpiF64 : InstPTX<(outs), (ins MEMpi:$d, RegF64:$a), +// "st.param.f64\t[$d], $a", []>; + // Stores defm STg : PTX_ST_ALL<"st.global", store_global>; defm STl : PTX_ST_ALL<"st.local", store_local>; diff --git a/lib/Target/PTX/PTXSubtarget.h b/lib/Target/PTX/PTXSubtarget.h index c8f8c3b..2ebe6cf 100644 --- a/lib/Target/PTX/PTXSubtarget.h +++ b/lib/Target/PTX/PTXSubtarget.h @@ -18,7 +18,7 @@ namespace llvm { class PTXSubtarget : public TargetSubtarget { - private: + public: /** * Enumeration of Shader Models supported by the back-end. @@ -41,6 +41,8 @@ namespace llvm { PTX_VERSION_2_3 /*< PTX Version 2.3 */ }; + private: + /// Shader Model supported on the target GPU. PTXShaderModelEnum PTXShaderModel; @@ -58,8 +60,10 @@ namespace llvm { bool Is64Bit; public: + PTXSubtarget(const std::string &TT, const std::string &FS, bool is64Bit); + // Target architecture accessors std::string getTargetString() const; std::string getPTXVersionString() const; @@ -80,6 +84,9 @@ namespace llvm { bool supportsPTX23() const { return PTXVersion >= PTX_VERSION_2_3; } + PTXShaderModelEnum getShaderModel() const { return PTXShaderModel; } + + std::string ParseSubtargetFeatures(const std::string &FS, const std::string &CPU); }; // class PTXSubtarget -- cgit v1.1 From a5ccb4e9745bd77d877f4735683a9ae31668b61b Mon Sep 17 00:00:00 2001 From: Justin Holewinski Date: Thu, 23 Jun 2011 18:10:05 +0000 Subject: PTX: Prevent DCE from eliminating st.param calls, and unify the handling of st.param and ld.param FIXME: Test cases still need to be updated git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133733 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/PTX/PTXAsmPrinter.cpp | 28 +++++++++++--- lib/Target/PTX/PTXISelDAGToDAG.cpp | 69 --------------------------------- lib/Target/PTX/PTXISelLowering.cpp | 8 ++-- lib/Target/PTX/PTXISelLowering.h | 2 +- lib/Target/PTX/PTXInstrInfo.td | 78 ++++++++++++++++++++++++-------------- 5 files changed, 78 insertions(+), 107 deletions(-) diff --git a/lib/Target/PTX/PTXAsmPrinter.cpp b/lib/Target/PTX/PTXAsmPrinter.cpp index 0b055c2..87b3903 100644 --- a/lib/Target/PTX/PTXAsmPrinter.cpp +++ b/lib/Target/PTX/PTXAsmPrinter.cpp @@ -63,6 +63,8 @@ public: const char *Modifier = 0); void printParamOperand(const MachineInstr *MI, int opNum, raw_ostream &OS, const char *Modifier = 0); + void printReturnOperand(const MachineInstr *MI, int opNum, raw_ostream &OS, + const char *Modifier = 0); void printPredicateOperand(const MachineInstr *MI, raw_ostream &O); // autogen'd. @@ -76,6 +78,7 @@ private: } // namespace static const char PARAM_PREFIX[] = "__param_"; +static const char RETURN_PREFIX[] = "__ret_"; static const char *getRegisterTypeName(unsigned RegNo) { #define TEST_REGCLS(cls, clsstr) \ @@ -298,6 +301,11 @@ void PTXAsmPrinter::printParamOperand(const MachineInstr *MI, int opNum, OS << PARAM_PREFIX << (int) MI->getOperand(opNum).getImm() + 1; } +void PTXAsmPrinter::printReturnOperand(const MachineInstr *MI, int opNum, + raw_ostream &OS, const char *Modifier) { + OS << RETURN_PREFIX << (int) MI->getOperand(opNum).getImm() + 1; +} + void PTXAsmPrinter::EmitVariableDeclaration(const GlobalVariable *gv) { // Check to see if this is a special global used by LLVM, if so, emit it. if (EmitSpecialLLVMGlobal(gv)) @@ -421,6 +429,8 @@ void PTXAsmPrinter::EmitFunctionDeclaration() { std::string decl = isKernel ? ".entry" : ".func"; + unsigned cnt = 0; + if (!isKernel) { decl += " ("; @@ -430,10 +440,18 @@ void PTXAsmPrinter::EmitFunctionDeclaration() { if (i != b) { decl += ", "; } - decl += ".reg ."; - decl += getRegisterTypeName(*i); - decl += " "; - decl += getRegisterName(*i); + if (ST.getShaderModel() >= PTXSubtarget::PTX_SM_2_0) { + decl += ".param .b"; + decl += utostr(*i); + decl += " "; + decl += RETURN_PREFIX; + decl += utostr(++cnt); + } else { + decl += ".reg ."; + decl += getRegisterTypeName(*i); + decl += " "; + decl += getRegisterName(*i); + } } decl += ")"; } @@ -444,7 +462,7 @@ void PTXAsmPrinter::EmitFunctionDeclaration() { decl += " ("; - unsigned cnt = 0; + cnt = 0; // Print parameters for (PTXMachineFunctionInfo::reg_iterator diff --git a/lib/Target/PTX/PTXISelDAGToDAG.cpp b/lib/Target/PTX/PTXISelDAGToDAG.cpp index 1cae8f3..9adfa62 100644 --- a/lib/Target/PTX/PTXISelDAGToDAG.cpp +++ b/lib/Target/PTX/PTXISelDAGToDAG.cpp @@ -42,9 +42,6 @@ class PTXDAGToDAGISel : public SelectionDAGISel { #include "PTXGenDAGISel.inc" private: - SDNode *SelectREAD_PARAM(SDNode *Node); - //SDNode *SelectSTORE_PARAM(SDNode *Node); - // We need this only because we can't match intruction BRAdp // pattern (PTXbrcond bb:$d, ...) in PTXInstrInfo.td SDNode *SelectBRCOND(SDNode *Node); @@ -69,10 +66,6 @@ PTXDAGToDAGISel::PTXDAGToDAGISel(PTXTargetMachine &TM, SDNode *PTXDAGToDAGISel::Select(SDNode *Node) { switch (Node->getOpcode()) { - case PTXISD::READ_PARAM: - return SelectREAD_PARAM(Node); - // case PTXISD::STORE_PARAM: - // return SelectSTORE_PARAM(Node); case ISD::BRCOND: return SelectBRCOND(Node); default: @@ -80,68 +73,6 @@ SDNode *PTXDAGToDAGISel::Select(SDNode *Node) { } } -SDNode *PTXDAGToDAGISel::SelectREAD_PARAM(SDNode *Node) { - SDValue index = Node->getOperand(1); - DebugLoc dl = Node->getDebugLoc(); - unsigned opcode; - - if (index.getOpcode() != ISD::TargetConstant) - llvm_unreachable("READ_PARAM: index is not ISD::TargetConstant"); - - if (Node->getValueType(0) == MVT::i16) { - opcode = PTX::LDpiU16; - } else if (Node->getValueType(0) == MVT::i32) { - opcode = PTX::LDpiU32; - } else if (Node->getValueType(0) == MVT::i64) { - opcode = PTX::LDpiU64; - } else if (Node->getValueType(0) == MVT::f32) { - opcode = PTX::LDpiF32; - } else if (Node->getValueType(0) == MVT::f64) { - opcode = PTX::LDpiF64; - } else { - llvm_unreachable("Unknown parameter type for ld.param"); - } - - return PTXInstrInfo:: - GetPTXMachineNode(CurDAG, opcode, dl, Node->getValueType(0), index); -} - -// SDNode *PTXDAGToDAGISel::SelectSTORE_PARAM(SDNode *Node) { -// SDValue Chain = Node->getOperand(0); -// SDValue index = Node->getOperand(1); -// SDValue value = Node->getOperand(2); -// DebugLoc dl = Node->getDebugLoc(); -// unsigned opcode; - -// if (index.getOpcode() != ISD::TargetConstant) -// llvm_unreachable("STORE_PARAM: index is not ISD::TargetConstant"); - -// if (value->getValueType(0) == MVT::i16) { -// opcode = PTX::STpiU16; -// } else if (value->getValueType(0) == MVT::i32) { -// opcode = PTX::STpiU32; -// } else if (value->getValueType(0) == MVT::i64) { -// opcode = PTX::STpiU64; -// } else if (value->getValueType(0) == MVT::f32) { -// opcode = PTX::STpiF32; -// } else if (value->getValueType(0) == MVT::f64) { -// opcode = PTX::STpiF64; -// } else { -// llvm_unreachable("Unknown parameter type for st.param"); -// } - -// SDVTList VTs = CurDAG->getVTList(MVT::Other, MVT::Glue); -// SDValue PredReg = CurDAG->getRegister(PTX::NoRegister, MVT::i1); -// SDValue PredOp = CurDAG->getTargetConstant(PTX::PRED_NORMAL, MVT::i32); -// SDValue Ops[] = { Chain, index, value, PredReg, PredOp }; -// //SDNode *RetNode = PTXInstrInfo:: -// // GetPTXMachineNode(CurDAG, opcode, dl, VTs, index, value); -// SDNode *RetNode = CurDAG->getMachineNode(opcode, dl, VTs, Ops, array_lengthof(Ops)); -// DEBUG(dbgs() << "SelectSTORE_PARAM: Selected: "); -// RetNode->dumpr(CurDAG); -// return RetNode; -// } - SDNode *PTXDAGToDAGISel::SelectBRCOND(SDNode *Node) { assert(Node->getNumOperands() >= 3); diff --git a/lib/Target/PTX/PTXISelLowering.cpp b/lib/Target/PTX/PTXISelLowering.cpp index 782d916..34660bf 100644 --- a/lib/Target/PTX/PTXISelLowering.cpp +++ b/lib/Target/PTX/PTXISelLowering.cpp @@ -105,8 +105,8 @@ const char *PTXTargetLowering::getTargetNodeName(unsigned Opcode) const { llvm_unreachable("Unknown opcode"); case PTXISD::COPY_ADDRESS: return "PTXISD::COPY_ADDRESS"; - case PTXISD::READ_PARAM: - return "PTXISD::READ_PARAM"; + case PTXISD::LOAD_PARAM: + return "PTXISD::LOAD_PARAM"; case PTXISD::STORE_PARAM: return "PTXISD::STORE_PARAM"; case PTXISD::EXIT: @@ -215,13 +215,13 @@ SDValue PTXTargetLowering:: // SM < 2.0 -> Use registers for arguments if (MFI->isKernel() || ST.getShaderModel() >= PTXSubtarget::PTX_SM_2_0) { - // We just need to emit the proper READ_PARAM ISDs + // We just need to emit the proper LOAD_PARAM ISDs for (unsigned i = 0, e = Ins.size(); i != e; ++i) { assert((!MFI->isKernel() || Ins[i].VT != MVT::i1) && "Kernels cannot take pred operands"); - SDValue ArgValue = DAG.getNode(PTXISD::READ_PARAM, dl, Ins[i].VT, Chain, + SDValue ArgValue = DAG.getNode(PTXISD::LOAD_PARAM, dl, Ins[i].VT, Chain, DAG.getTargetConstant(i, MVT::i32)); InVals.push_back(ArgValue); diff --git a/lib/Target/PTX/PTXISelLowering.h b/lib/Target/PTX/PTXISelLowering.h index e33c0bd..4318541 100644 --- a/lib/Target/PTX/PTXISelLowering.h +++ b/lib/Target/PTX/PTXISelLowering.h @@ -24,7 +24,7 @@ class PTXTargetMachine; namespace PTXISD { enum NodeType { FIRST_NUMBER = ISD::BUILTIN_OP_END, - READ_PARAM, + LOAD_PARAM, STORE_PARAM, EXIT, RET, diff --git a/lib/Target/PTX/PTXInstrInfo.td b/lib/Target/PTX/PTXInstrInfo.td index b5597d4..1c18c4a 100644 --- a/lib/Target/PTX/PTXInstrInfo.td +++ b/lib/Target/PTX/PTXInstrInfo.td @@ -163,6 +163,10 @@ def MEMpi : Operand { let PrintMethod = "printParamOperand"; let MIOperandInfo = (ops i32imm); } +def MEMret : Operand { + let PrintMethod = "printReturnOperand"; + let MIOperandInfo = (ops i32imm); +} // Branch & call targets have OtherVT type. def brtarget : Operand; @@ -185,6 +189,10 @@ def PTXret def PTXcopyaddress : SDNode<"PTXISD::COPY_ADDRESS", SDTypeProfile<1, 1, []>, []>; +// Load/store .param space +def PTXloadparam + : SDNode<"PTXISD::LOAD_PARAM", SDTypeProfile<1, 1, [SDTCisVT<1, i32>]>, + [SDNPHasChain, SDNPOutGlue, SDNPOptInGlue]>; def PTXstoreparam : SDNode<"PTXISD::STORE_PARAM", SDTypeProfile<0, 2, [SDTCisVT<0, i32>]>, [SDNPHasChain, SDNPOutGlue, SDNPOptInGlue]>; @@ -821,34 +829,48 @@ defm LDc : PTX_LD_ALL<"ld.const", load_constant>; defm LDl : PTX_LD_ALL<"ld.local", load_local>; defm LDs : PTX_LD_ALL<"ld.shared", load_shared>; -// This is a special instruction that is manually inserted for parameters -def LDpiU16 : InstPTX<(outs RegI16:$d), (ins MEMpi:$a), - "ld.param.u16\t$d, [$a]", []>; -def LDpiU32 : InstPTX<(outs RegI32:$d), (ins MEMpi:$a), - "ld.param.u32\t$d, [$a]", []>; -def LDpiU64 : InstPTX<(outs RegI64:$d), (ins MEMpi:$a), - "ld.param.u64\t$d, [$a]", []>; -def LDpiF32 : InstPTX<(outs RegF32:$d), (ins MEMpi:$a), - "ld.param.f32\t$d, [$a]", []>; -def LDpiF64 : InstPTX<(outs RegF64:$d), (ins MEMpi:$a), - "ld.param.f64\t$d, [$a]", []>; - -// def STpiPred : InstPTX<(outs), (ins i1imm:$d, RegPred:$a), -// "st.param.pred\t[$d], $a", -// [(PTXstoreparam imm:$d, RegPred:$a)]>; -// def STpiU16 : InstPTX<(outs), (ins i16imm:$d, RegI16:$a), -// "st.param.u16\t[$d], $a", -// [(PTXstoreparam imm:$d, RegI16:$a)]>; -def STpiU32 : InstPTX<(outs), (ins i32imm:$d, RegI32:$a), - "st.param.u32\t[$d], $a", - [(PTXstoreparam timm:$d, RegI32:$a)]>; -// def STpiU64 : InstPTX<(outs), (ins i64imm:$d, RegI64:$a), -// "st.param.u64\t[$d], $a", -// [(PTXstoreparam imm:$d, RegI64:$a)]>; -// def STpiF32 : InstPTX<(outs), (ins MEMpi:$d, RegF32:$a), -// "st.param.f32\t[$d], $a", []>; -// def STpiF64 : InstPTX<(outs), (ins MEMpi:$d, RegF64:$a), -// "st.param.f64\t[$d], $a", []>; +// These instructions are used to load/store from the .param space for +// device and kernel parameters + +let hasSideEffects = 1 in { + def LDpiPred : InstPTX<(outs RegPred:$d), (ins MEMpi:$a), + "ld.param.pred\t$d, [$a]", + [(set RegPred:$d, (PTXloadparam timm:$a))]>; + def LDpiU16 : InstPTX<(outs RegI16:$d), (ins MEMpi:$a), + "ld.param.u16\t$d, [$a]", + [(set RegI16:$d, (PTXloadparam timm:$a))]>; + def LDpiU32 : InstPTX<(outs RegI32:$d), (ins MEMpi:$a), + "ld.param.u32\t$d, [$a]", + [(set RegI32:$d, (PTXloadparam timm:$a))]>; + def LDpiU64 : InstPTX<(outs RegI64:$d), (ins MEMpi:$a), + "ld.param.u64\t$d, [$a]", + [(set RegI64:$d, (PTXloadparam timm:$a))]>; + def LDpiF32 : InstPTX<(outs RegF32:$d), (ins MEMpi:$a), + "ld.param.f32\t$d, [$a]", + [(set RegF32:$d, (PTXloadparam timm:$a))]>; + def LDpiF64 : InstPTX<(outs RegF64:$d), (ins MEMpi:$a), + "ld.param.f64\t$d, [$a]", + [(set RegF64:$d, (PTXloadparam timm:$a))]>; + + def STpiPred : InstPTX<(outs), (ins MEMret:$d, RegPred:$a), + "st.param.pred\t[$d], $a", + [(PTXstoreparam timm:$d, RegPred:$a)]>; + def STpiU16 : InstPTX<(outs), (ins MEMret:$d, RegI16:$a), + "st.param.u16\t[$d], $a", + [(PTXstoreparam timm:$d, RegI16:$a)]>; + def STpiU32 : InstPTX<(outs), (ins MEMret:$d, RegI32:$a), + "st.param.u32\t[$d], $a", + [(PTXstoreparam timm:$d, RegI32:$a)]>; + def STpiU64 : InstPTX<(outs), (ins MEMret:$d, RegI64:$a), + "st.param.u64\t[$d], $a", + [(PTXstoreparam timm:$d, RegI64:$a)]>; + def STpiF32 : InstPTX<(outs), (ins MEMret:$d, RegF32:$a), + "st.param.f32\t[$d], $a", + [(PTXstoreparam timm:$d, RegF32:$a)]>; + def STpiF64 : InstPTX<(outs), (ins MEMret:$d, RegF64:$a), + "st.param.f64\t[$d], $a", + [(PTXstoreparam timm:$d, RegF64:$a)]>; +} // Stores defm STg : PTX_ST_ALL<"st.global", store_global>; -- cgit v1.1 From 486ca24c08ef7b572336649d1a8cca0cb020a49b Mon Sep 17 00:00:00 2001 From: Justin Holewinski Date: Thu, 23 Jun 2011 18:10:07 +0000 Subject: PTX: Whitespace fixes and remove commented out code git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133734 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/PTX/PTXAsmPrinter.cpp | 35 ----------------------------------- lib/Target/PTX/PTXISelLowering.cpp | 1 - 2 files changed, 36 deletions(-) diff --git a/lib/Target/PTX/PTXAsmPrinter.cpp b/lib/Target/PTX/PTXAsmPrinter.cpp index 87b3903..6686cdd 100644 --- a/lib/Target/PTX/PTXAsmPrinter.cpp +++ b/lib/Target/PTX/PTXAsmPrinter.cpp @@ -486,41 +486,6 @@ void PTXAsmPrinter::EmitFunctionDeclaration() { } decl += ")"; - // // Print parameter list - // if (!MFI->argRegEmpty()) { - // decl += " ("; - // if (isKernel) { - // unsigned cnt = 0; - // for(PTXMachineFunctionInfo::reg_iterator - // i = MFI->argRegBegin(), e = MFI->argRegEnd(), b = i; - // i != e; ++i) { - // reg = *i; - // assert(reg != PTX::NoRegister && "Not a valid register!"); - // if (i != b) - // decl += ", "; - // decl += ".param ."; - // decl += getRegisterTypeName(reg); - // decl += " "; - // decl += PARAM_PREFIX; - // decl += utostr(++cnt); - // } - // } else { - // for (PTXMachineFunctionInfo::reg_iterator - // i = MFI->argRegBegin(), e = MFI->argRegEnd(), b = i; - // i != e; ++i) { - // reg = *i; - // assert(reg != PTX::NoRegister && "Not a valid register!"); - // if (i != b) - // decl += ", "; - // decl += ".reg ."; - // decl += getRegisterTypeName(reg); - // decl += " "; - // decl += getRegisterName(reg); - // } - // } - // decl += ")"; - // } - OutStreamer.EmitRawText(Twine(decl)); } diff --git a/lib/Target/PTX/PTXISelLowering.cpp b/lib/Target/PTX/PTXISelLowering.cpp index 34660bf..cb4a5d3 100644 --- a/lib/Target/PTX/PTXISelLowering.cpp +++ b/lib/Target/PTX/PTXISelLowering.cpp @@ -213,7 +213,6 @@ SDValue PTXTargetLowering:: // We do one of two things here: // IsKernel || SM >= 2.0 -> Use param space for arguments // SM < 2.0 -> Use registers for arguments - if (MFI->isKernel() || ST.getShaderModel() >= PTXSubtarget::PTX_SM_2_0) { // We just need to emit the proper LOAD_PARAM ISDs for (unsigned i = 0, e = Ins.size(); i != e; ++i) { -- cgit v1.1 From 6b1131e5ff1543dbc1f2cf5d64dcecab42516c51 Mon Sep 17 00:00:00 2001 From: Justin Holewinski Date: Thu, 23 Jun 2011 18:10:08 +0000 Subject: PTX: Fixup test cases for device param changes git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133735 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/CodeGen/PTX/intrinsic.ll | 2 +- test/CodeGen/PTX/llvm-intrinsic.ll | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/CodeGen/PTX/intrinsic.ll b/test/CodeGen/PTX/intrinsic.ll index cea4182..af987d6 100644 --- a/test/CodeGen/PTX/intrinsic.ll +++ b/test/CodeGen/PTX/intrinsic.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -march=ptx32 -mattr=+ptx20,+sm20 | FileCheck %s +; RUN: llc < %s -march=ptx32 -mattr=+ptx20 | FileCheck %s define ptx_device i32 @test_tid_x() { ; CHECK: mov.u32 r0, %tid.x; diff --git a/test/CodeGen/PTX/llvm-intrinsic.ll b/test/CodeGen/PTX/llvm-intrinsic.ll index a317645..9c532c1 100644 --- a/test/CodeGen/PTX/llvm-intrinsic.ll +++ b/test/CodeGen/PTX/llvm-intrinsic.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -march=ptx32 -mattr=+ptx20,+sm20 | FileCheck %s +; RUN: llc < %s -march=ptx32 -mattr=+ptx20 | FileCheck %s define ptx_device float @test_sqrt_f32(float %x) { entry: -- cgit v1.1 From d8149c1bef75e15010cce4c4510b7f68ecde80a5 Mon Sep 17 00:00:00 2001 From: Justin Holewinski Date: Thu, 23 Jun 2011 18:10:13 +0000 Subject: PTX: Always use registers for return values, but use .param space for device parameters if SM >= 2.0 - Update test cases to be more robust against register allocation changes - Bump up the number of registers to 128 per type - Include Python script to re-generate register file with any number of registers git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133736 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/PTX/PTXAsmPrinter.cpp | 17 +- lib/Target/PTX/PTXCallingConv.td | 29 +- lib/Target/PTX/PTXISelLowering.cpp | 50 +-- lib/Target/PTX/PTXMachineFunctionInfo.h | 10 +- lib/Target/PTX/PTXRegisterInfo.td | 564 +++++++++++++++++++++++++++++--- lib/Target/PTX/generate-register-td.py | 163 +++++++++ test/CodeGen/PTX/add.ll | 20 +- test/CodeGen/PTX/aggregates.ll | 23 ++ test/CodeGen/PTX/bitwise.ll | 6 +- test/CodeGen/PTX/bra.ll | 6 +- test/CodeGen/PTX/cvt.ll | 80 ++--- test/CodeGen/PTX/fdiv-sm10.ll | 4 +- test/CodeGen/PTX/fdiv-sm13.ll | 4 +- test/CodeGen/PTX/fneg.ll | 4 +- test/CodeGen/PTX/ld.ll | 150 ++++----- test/CodeGen/PTX/llvm-intrinsic.ll | 12 +- test/CodeGen/PTX/mad.ll | 4 +- test/CodeGen/PTX/mov.ll | 20 +- test/CodeGen/PTX/mul.ll | 8 +- test/CodeGen/PTX/parameter-order.ll | 4 +- test/CodeGen/PTX/selp.ll | 8 +- test/CodeGen/PTX/setp.ll | 92 +++--- test/CodeGen/PTX/shl.ll | 6 +- test/CodeGen/PTX/shr.ll | 12 +- test/CodeGen/PTX/st.ll | 130 ++++---- test/CodeGen/PTX/sub.ll | 20 +- 26 files changed, 1043 insertions(+), 403 deletions(-) create mode 100755 lib/Target/PTX/generate-register-td.py create mode 100644 test/CodeGen/PTX/aggregates.ll diff --git a/lib/Target/PTX/PTXAsmPrinter.cpp b/lib/Target/PTX/PTXAsmPrinter.cpp index 6686cdd..5d7e4c3 100644 --- a/lib/Target/PTX/PTXAsmPrinter.cpp +++ b/lib/Target/PTX/PTXAsmPrinter.cpp @@ -433,25 +433,16 @@ void PTXAsmPrinter::EmitFunctionDeclaration() { if (!isKernel) { decl += " ("; - for (PTXMachineFunctionInfo::ret_iterator i = MFI->retRegBegin(), e = MFI->retRegEnd(), b = i; i != e; ++i) { if (i != b) { decl += ", "; } - if (ST.getShaderModel() >= PTXSubtarget::PTX_SM_2_0) { - decl += ".param .b"; - decl += utostr(*i); - decl += " "; - decl += RETURN_PREFIX; - decl += utostr(++cnt); - } else { - decl += ".reg ."; - decl += getRegisterTypeName(*i); - decl += " "; - decl += getRegisterName(*i); - } + decl += ".reg ."; + decl += getRegisterTypeName(*i); + decl += " "; + decl += getRegisterName(*i); } decl += ")"; } diff --git a/lib/Target/PTX/PTXCallingConv.td b/lib/Target/PTX/PTXCallingConv.td index 4d7759b..3e3ff48 100644 --- a/lib/Target/PTX/PTXCallingConv.td +++ b/lib/Target/PTX/PTXCallingConv.td @@ -1,3 +1,4 @@ + //===--- PTXCallingConv.td - Calling Conventions -----------*- tablegen -*-===// // // The LLVM Compiler Infrastructure @@ -11,26 +12,18 @@ // //===----------------------------------------------------------------------===// -// Currently, we reserve one register of each type for return values and let -// the rest be used for parameters. This is a dirty hack, but I am not sure -// how to tell LLVM that registers used for parameter passing cannot be used -// for return values. - -// PTX Calling Conventions +// PTX Formal Parameter Calling Convention def CC_PTX : CallingConv<[ - CCIfType<[i1], CCAssignToReg<[P1, P2, P3, P4, P5, P6, P7]>>, - CCIfType<[i16], CCAssignToReg<[RH1, RH2, RH3, RH4, RH5, RH6, RH7]>>, - CCIfType<[i32, f32], CCAssignToReg<[R1, R2, R3, R4, R5, R6, R7]>>, - CCIfType<[i64, f64], CCAssignToReg<[RD1, RD2, RD3, RD4, RD5, RD6, RD7]>> + CCIfType<[i1], CCAssignToReg<[P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122, P123, P124, P125, P126, P127]>>, + CCIfType<[i16], CCAssignToReg<[RH12, RH13, RH14, RH15, RH16, RH17, RH18, RH19, RH20, RH21, RH22, RH23, RH24, RH25, RH26, RH27, RH28, RH29, RH30, RH31, RH32, RH33, RH34, RH35, RH36, RH37, RH38, RH39, RH40, RH41, RH42, RH43, RH44, RH45, RH46, RH47, RH48, RH49, RH50, RH51, RH52, RH53, RH54, RH55, RH56, RH57, RH58, RH59, RH60, RH61, RH62, RH63, RH64, RH65, RH66, RH67, RH68, RH69, RH70, RH71, RH72, RH73, RH74, RH75, RH76, RH77, RH78, RH79, RH80, RH81, RH82, RH83, RH84, RH85, RH86, RH87, RH88, RH89, RH90, RH91, RH92, RH93, RH94, RH95, RH96, RH97, RH98, RH99, RH100, RH101, RH102, RH103, RH104, RH105, RH106, RH107, RH108, RH109, RH110, RH111, RH112, RH113, RH114, RH115, RH116, RH117, RH118, RH119, RH120, RH121, RH122, RH123, RH124, RH125, RH126, RH127]>>, + CCIfType<[i32,f32], CCAssignToReg<[R12, R13, R14, R15, R16, R17, R18, R19, R20, R21, R22, R23, R24, R25, R26, R27, R28, R29, R30, R31, R32, R33, R34, R35, R36, R37, R38, R39, R40, R41, R42, R43, R44, R45, R46, R47, R48, R49, R50, R51, R52, R53, R54, R55, R56, R57, R58, R59, R60, R61, R62, R63, R64, R65, R66, R67, R68, R69, R70, R71, R72, R73, R74, R75, R76, R77, R78, R79, R80, R81, R82, R83, R84, R85, R86, R87, R88, R89, R90, R91, R92, R93, R94, R95, R96, R97, R98, R99, R100, R101, R102, R103, R104, R105, R106, R107, R108, R109, R110, R111, R112, R113, R114, R115, R116, R117, R118, R119, R120, R121, R122, R123, R124, R125, R126, R127]>>, + CCIfType<[i64,f64], CCAssignToReg<[RD12, RD13, RD14, RD15, RD16, RD17, RD18, RD19, RD20, RD21, RD22, RD23, RD24, RD25, RD26, RD27, RD28, RD29, RD30, RD31, RD32, RD33, RD34, RD35, RD36, RD37, RD38, RD39, RD40, RD41, RD42, RD43, RD44, RD45, RD46, RD47, RD48, RD49, RD50, RD51, RD52, RD53, RD54, RD55, RD56, RD57, RD58, RD59, RD60, RD61, RD62, RD63, RD64, RD65, RD66, RD67, RD68, RD69, RD70, RD71, RD72, RD73, RD74, RD75, RD76, RD77, RD78, RD79, RD80, RD81, RD82, RD83, RD84, RD85, RD86, RD87, RD88, RD89, RD90, RD91, RD92, RD93, RD94, RD95, RD96, RD97, RD98, RD99, RD100, RD101, RD102, RD103, RD104, RD105, RD106, RD107, RD108, RD109, RD110, RD111, RD112, RD113, RD114, RD115, RD116, RD117, RD118, RD119, RD120, RD121, RD122, RD123, RD124, RD125, RD126, RD127]>> ]>; -//===----------------------------------------------------------------------===// -// Return Value Calling Conventions -//===----------------------------------------------------------------------===// - +// PTX Return Value Calling Convention def RetCC_PTX : CallingConv<[ - CCIfType<[i1], CCAssignToReg<[P0]>>, - CCIfType<[i16], CCAssignToReg<[RH0]>>, - CCIfType<[i32, f32], CCAssignToReg<[R0]>>, - CCIfType<[i64, f64], CCAssignToReg<[RD0]>> + CCIfType<[i1], CCAssignToReg<[P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11]>>, + CCIfType<[i16], CCAssignToReg<[RH0, RH1, RH2, RH3, RH4, RH5, RH6, RH7, RH8, RH9, RH10, RH11]>>, + CCIfType<[i32,f32], CCAssignToReg<[R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11]>>, + CCIfType<[i64,f64], CCAssignToReg<[RD0, RD1, RD2, RD3, RD4, RD5, RD6, RD7, RD8, RD9, RD10, RD11]>> ]>; diff --git a/lib/Target/PTX/PTXISelLowering.cpp b/lib/Target/PTX/PTXISelLowering.cpp index cb4a5d3..c821493 100644 --- a/lib/Target/PTX/PTXISelLowering.cpp +++ b/lib/Target/PTX/PTXISelLowering.cpp @@ -307,49 +307,35 @@ SDValue PTXTargetLowering:: MachineFunction& MF = DAG.getMachineFunction(); PTXMachineFunctionInfo *MFI = MF.getInfo(); - const PTXSubtarget& ST = getTargetMachine().getSubtarget(); SDValue Flag; - if (ST.getShaderModel() >= PTXSubtarget::PTX_SM_2_0) { - // For SM 2.0+, we return arguments in the param space - for (unsigned i = 0, e = Outs.size(); i != e; ++i) { - SDVTList VTs = DAG.getVTList(MVT::Other, MVT::Glue); - SDValue ParamIndex = DAG.getTargetConstant(i, MVT::i32); - SDValue Ops[] = { Chain, ParamIndex, OutVals[i], Flag }; - Chain = DAG.getNode(PTXISD::STORE_PARAM, dl, VTs, Ops, - Flag.getNode() ? 4 : 3); - Flag = Chain.getValue(1); - // Instead of storing a physical register in our argument list, we just - // store the total size of the parameter, in bits. The ASM printer - // knows how to process this. - MFI->addRetReg(Outs[i].VT.getStoreSizeInBits()); - } - } else { - // For SM < 2.0, we return arguments in registers - SmallVector RVLocs; - CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), - getTargetMachine(), RVLocs, *DAG.getContext()); + // Even though we could use the .param space for return arguments for + // device functions if SM >= 2.0 and the number of return arguments is + // only 1, we just always use registers since this makes the codegen + // easier. + SmallVector RVLocs; + CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), + getTargetMachine(), RVLocs, *DAG.getContext()); - CCInfo.AnalyzeReturn(Outs, RetCC_PTX); + CCInfo.AnalyzeReturn(Outs, RetCC_PTX); - for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) { - CCValAssign& VA = RVLocs[i]; + for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) { + CCValAssign& VA = RVLocs[i]; - assert(VA.isRegLoc() && "CCValAssign must be RegLoc"); + assert(VA.isRegLoc() && "CCValAssign must be RegLoc"); - unsigned Reg = VA.getLocReg(); + unsigned Reg = VA.getLocReg(); - DAG.getMachineFunction().getRegInfo().addLiveOut(Reg); + DAG.getMachineFunction().getRegInfo().addLiveOut(Reg); - Chain = DAG.getCopyToReg(Chain, dl, Reg, OutVals[i], Flag); + Chain = DAG.getCopyToReg(Chain, dl, Reg, OutVals[i], Flag); - // Guarantee that all emitted copies are stuck together, - // avoiding something bad - Flag = Chain.getValue(1); + // Guarantee that all emitted copies are stuck together, + // avoiding something bad + Flag = Chain.getValue(1); - MFI->addRetReg(Reg); - } + MFI->addRetReg(Reg); } if (Flag.getNode() == 0) { diff --git a/lib/Target/PTX/PTXMachineFunctionInfo.h b/lib/Target/PTX/PTXMachineFunctionInfo.h index 1da4b5d..9d65f5b 100644 --- a/lib/Target/PTX/PTXMachineFunctionInfo.h +++ b/lib/Target/PTX/PTXMachineFunctionInfo.h @@ -26,7 +26,7 @@ class PTXMachineFunctionInfo : public MachineFunctionInfo { private: bool is_kernel; std::vector reg_arg, reg_local_var; - DenseSet reg_ret; + std::vector reg_ret; bool _isDoneAddArg; public: @@ -40,7 +40,11 @@ public: void addArgReg(unsigned reg) { reg_arg.push_back(reg); } void addLocalVarReg(unsigned reg) { reg_local_var.push_back(reg); } - void addRetReg(unsigned reg) { reg_ret.insert(reg); } + void addRetReg(unsigned reg) { + if (!isRetReg(reg)) { + reg_ret.push_back(reg); + } + } void doneAddArg(void) { _isDoneAddArg = true; @@ -51,7 +55,7 @@ public: typedef std::vector::const_iterator reg_iterator; typedef std::vector::const_reverse_iterator reg_reverse_iterator; - typedef DenseSet::const_iterator ret_iterator; + typedef std::vector::const_iterator ret_iterator; bool argRegEmpty() const { return reg_arg.empty(); } int getNumArg() const { return reg_arg.size(); } diff --git a/lib/Target/PTX/PTXRegisterInfo.td b/lib/Target/PTX/PTXRegisterInfo.td index 08a39a8..1313d24 100644 --- a/lib/Target/PTX/PTXRegisterInfo.td +++ b/lib/Target/PTX/PTXRegisterInfo.td @@ -1,3 +1,4 @@ + //===- PTXRegisterInfo.td - PTX Register defs ----------------*- tblgen -*-===// // // The LLVM Compiler Infrastructure @@ -21,55 +22,534 @@ class PTXReg : Register { ///===- Predicate Registers -----------------------------------------------===// -def P0 : PTXReg<"p0">; -def P1 : PTXReg<"p1">; -def P2 : PTXReg<"p2">; -def P3 : PTXReg<"p3">; -def P4 : PTXReg<"p4">; -def P5 : PTXReg<"p5">; -def P6 : PTXReg<"p6">; -def P7 : PTXReg<"p7">; +def P0 : PTXReg<"p0">; +def P1 : PTXReg<"p1">; +def P2 : PTXReg<"p2">; +def P3 : PTXReg<"p3">; +def P4 : PTXReg<"p4">; +def P5 : PTXReg<"p5">; +def P6 : PTXReg<"p6">; +def P7 : PTXReg<"p7">; +def P8 : PTXReg<"p8">; +def P9 : PTXReg<"p9">; +def P10 : PTXReg<"p10">; +def P11 : PTXReg<"p11">; +def P12 : PTXReg<"p12">; +def P13 : PTXReg<"p13">; +def P14 : PTXReg<"p14">; +def P15 : PTXReg<"p15">; +def P16 : PTXReg<"p16">; +def P17 : PTXReg<"p17">; +def P18 : PTXReg<"p18">; +def P19 : PTXReg<"p19">; +def P20 : PTXReg<"p20">; +def P21 : PTXReg<"p21">; +def P22 : PTXReg<"p22">; +def P23 : PTXReg<"p23">; +def P24 : PTXReg<"p24">; +def P25 : PTXReg<"p25">; +def P26 : PTXReg<"p26">; +def P27 : PTXReg<"p27">; +def P28 : PTXReg<"p28">; +def P29 : PTXReg<"p29">; +def P30 : PTXReg<"p30">; +def P31 : PTXReg<"p31">; +def P32 : PTXReg<"p32">; +def P33 : PTXReg<"p33">; +def P34 : PTXReg<"p34">; +def P35 : PTXReg<"p35">; +def P36 : PTXReg<"p36">; +def P37 : PTXReg<"p37">; +def P38 : PTXReg<"p38">; +def P39 : PTXReg<"p39">; +def P40 : PTXReg<"p40">; +def P41 : PTXReg<"p41">; +def P42 : PTXReg<"p42">; +def P43 : PTXReg<"p43">; +def P44 : PTXReg<"p44">; +def P45 : PTXReg<"p45">; +def P46 : PTXReg<"p46">; +def P47 : PTXReg<"p47">; +def P48 : PTXReg<"p48">; +def P49 : PTXReg<"p49">; +def P50 : PTXReg<"p50">; +def P51 : PTXReg<"p51">; +def P52 : PTXReg<"p52">; +def P53 : PTXReg<"p53">; +def P54 : PTXReg<"p54">; +def P55 : PTXReg<"p55">; +def P56 : PTXReg<"p56">; +def P57 : PTXReg<"p57">; +def P58 : PTXReg<"p58">; +def P59 : PTXReg<"p59">; +def P60 : PTXReg<"p60">; +def P61 : PTXReg<"p61">; +def P62 : PTXReg<"p62">; +def P63 : PTXReg<"p63">; +def P64 : PTXReg<"p64">; +def P65 : PTXReg<"p65">; +def P66 : PTXReg<"p66">; +def P67 : PTXReg<"p67">; +def P68 : PTXReg<"p68">; +def P69 : PTXReg<"p69">; +def P70 : PTXReg<"p70">; +def P71 : PTXReg<"p71">; +def P72 : PTXReg<"p72">; +def P73 : PTXReg<"p73">; +def P74 : PTXReg<"p74">; +def P75 : PTXReg<"p75">; +def P76 : PTXReg<"p76">; +def P77 : PTXReg<"p77">; +def P78 : PTXReg<"p78">; +def P79 : PTXReg<"p79">; +def P80 : PTXReg<"p80">; +def P81 : PTXReg<"p81">; +def P82 : PTXReg<"p82">; +def P83 : PTXReg<"p83">; +def P84 : PTXReg<"p84">; +def P85 : PTXReg<"p85">; +def P86 : PTXReg<"p86">; +def P87 : PTXReg<"p87">; +def P88 : PTXReg<"p88">; +def P89 : PTXReg<"p89">; +def P90 : PTXReg<"p90">; +def P91 : PTXReg<"p91">; +def P92 : PTXReg<"p92">; +def P93 : PTXReg<"p93">; +def P94 : PTXReg<"p94">; +def P95 : PTXReg<"p95">; +def P96 : PTXReg<"p96">; +def P97 : PTXReg<"p97">; +def P98 : PTXReg<"p98">; +def P99 : PTXReg<"p99">; +def P100 : PTXReg<"p100">; +def P101 : PTXReg<"p101">; +def P102 : PTXReg<"p102">; +def P103 : PTXReg<"p103">; +def P104 : PTXReg<"p104">; +def P105 : PTXReg<"p105">; +def P106 : PTXReg<"p106">; +def P107 : PTXReg<"p107">; +def P108 : PTXReg<"p108">; +def P109 : PTXReg<"p109">; +def P110 : PTXReg<"p110">; +def P111 : PTXReg<"p111">; +def P112 : PTXReg<"p112">; +def P113 : PTXReg<"p113">; +def P114 : PTXReg<"p114">; +def P115 : PTXReg<"p115">; +def P116 : PTXReg<"p116">; +def P117 : PTXReg<"p117">; +def P118 : PTXReg<"p118">; +def P119 : PTXReg<"p119">; +def P120 : PTXReg<"p120">; +def P121 : PTXReg<"p121">; +def P122 : PTXReg<"p122">; +def P123 : PTXReg<"p123">; +def P124 : PTXReg<"p124">; +def P125 : PTXReg<"p125">; +def P126 : PTXReg<"p126">; +def P127 : PTXReg<"p127">; -///===- 16-bit Integer Registers ------------------------------------------===// +///===- 16-Bit Registers --------------------------------------------------===// -def RH0 : PTXReg<"rh0">; -def RH1 : PTXReg<"rh1">; -def RH2 : PTXReg<"rh2">; -def RH3 : PTXReg<"rh3">; -def RH4 : PTXReg<"rh4">; -def RH5 : PTXReg<"rh5">; -def RH6 : PTXReg<"rh6">; -def RH7 : PTXReg<"rh7">; +def RH0 : PTXReg<"rh0">; +def RH1 : PTXReg<"rh1">; +def RH2 : PTXReg<"rh2">; +def RH3 : PTXReg<"rh3">; +def RH4 : PTXReg<"rh4">; +def RH5 : PTXReg<"rh5">; +def RH6 : PTXReg<"rh6">; +def RH7 : PTXReg<"rh7">; +def RH8 : PTXReg<"rh8">; +def RH9 : PTXReg<"rh9">; +def RH10 : PTXReg<"rh10">; +def RH11 : PTXReg<"rh11">; +def RH12 : PTXReg<"rh12">; +def RH13 : PTXReg<"rh13">; +def RH14 : PTXReg<"rh14">; +def RH15 : PTXReg<"rh15">; +def RH16 : PTXReg<"rh16">; +def RH17 : PTXReg<"rh17">; +def RH18 : PTXReg<"rh18">; +def RH19 : PTXReg<"rh19">; +def RH20 : PTXReg<"rh20">; +def RH21 : PTXReg<"rh21">; +def RH22 : PTXReg<"rh22">; +def RH23 : PTXReg<"rh23">; +def RH24 : PTXReg<"rh24">; +def RH25 : PTXReg<"rh25">; +def RH26 : PTXReg<"rh26">; +def RH27 : PTXReg<"rh27">; +def RH28 : PTXReg<"rh28">; +def RH29 : PTXReg<"rh29">; +def RH30 : PTXReg<"rh30">; +def RH31 : PTXReg<"rh31">; +def RH32 : PTXReg<"rh32">; +def RH33 : PTXReg<"rh33">; +def RH34 : PTXReg<"rh34">; +def RH35 : PTXReg<"rh35">; +def RH36 : PTXReg<"rh36">; +def RH37 : PTXReg<"rh37">; +def RH38 : PTXReg<"rh38">; +def RH39 : PTXReg<"rh39">; +def RH40 : PTXReg<"rh40">; +def RH41 : PTXReg<"rh41">; +def RH42 : PTXReg<"rh42">; +def RH43 : PTXReg<"rh43">; +def RH44 : PTXReg<"rh44">; +def RH45 : PTXReg<"rh45">; +def RH46 : PTXReg<"rh46">; +def RH47 : PTXReg<"rh47">; +def RH48 : PTXReg<"rh48">; +def RH49 : PTXReg<"rh49">; +def RH50 : PTXReg<"rh50">; +def RH51 : PTXReg<"rh51">; +def RH52 : PTXReg<"rh52">; +def RH53 : PTXReg<"rh53">; +def RH54 : PTXReg<"rh54">; +def RH55 : PTXReg<"rh55">; +def RH56 : PTXReg<"rh56">; +def RH57 : PTXReg<"rh57">; +def RH58 : PTXReg<"rh58">; +def RH59 : PTXReg<"rh59">; +def RH60 : PTXReg<"rh60">; +def RH61 : PTXReg<"rh61">; +def RH62 : PTXReg<"rh62">; +def RH63 : PTXReg<"rh63">; +def RH64 : PTXReg<"rh64">; +def RH65 : PTXReg<"rh65">; +def RH66 : PTXReg<"rh66">; +def RH67 : PTXReg<"rh67">; +def RH68 : PTXReg<"rh68">; +def RH69 : PTXReg<"rh69">; +def RH70 : PTXReg<"rh70">; +def RH71 : PTXReg<"rh71">; +def RH72 : PTXReg<"rh72">; +def RH73 : PTXReg<"rh73">; +def RH74 : PTXReg<"rh74">; +def RH75 : PTXReg<"rh75">; +def RH76 : PTXReg<"rh76">; +def RH77 : PTXReg<"rh77">; +def RH78 : PTXReg<"rh78">; +def RH79 : PTXReg<"rh79">; +def RH80 : PTXReg<"rh80">; +def RH81 : PTXReg<"rh81">; +def RH82 : PTXReg<"rh82">; +def RH83 : PTXReg<"rh83">; +def RH84 : PTXReg<"rh84">; +def RH85 : PTXReg<"rh85">; +def RH86 : PTXReg<"rh86">; +def RH87 : PTXReg<"rh87">; +def RH88 : PTXReg<"rh88">; +def RH89 : PTXReg<"rh89">; +def RH90 : PTXReg<"rh90">; +def RH91 : PTXReg<"rh91">; +def RH92 : PTXReg<"rh92">; +def RH93 : PTXReg<"rh93">; +def RH94 : PTXReg<"rh94">; +def RH95 : PTXReg<"rh95">; +def RH96 : PTXReg<"rh96">; +def RH97 : PTXReg<"rh97">; +def RH98 : PTXReg<"rh98">; +def RH99 : PTXReg<"rh99">; +def RH100 : PTXReg<"rh100">; +def RH101 : PTXReg<"rh101">; +def RH102 : PTXReg<"rh102">; +def RH103 : PTXReg<"rh103">; +def RH104 : PTXReg<"rh104">; +def RH105 : PTXReg<"rh105">; +def RH106 : PTXReg<"rh106">; +def RH107 : PTXReg<"rh107">; +def RH108 : PTXReg<"rh108">; +def RH109 : PTXReg<"rh109">; +def RH110 : PTXReg<"rh110">; +def RH111 : PTXReg<"rh111">; +def RH112 : PTXReg<"rh112">; +def RH113 : PTXReg<"rh113">; +def RH114 : PTXReg<"rh114">; +def RH115 : PTXReg<"rh115">; +def RH116 : PTXReg<"rh116">; +def RH117 : PTXReg<"rh117">; +def RH118 : PTXReg<"rh118">; +def RH119 : PTXReg<"rh119">; +def RH120 : PTXReg<"rh120">; +def RH121 : PTXReg<"rh121">; +def RH122 : PTXReg<"rh122">; +def RH123 : PTXReg<"rh123">; +def RH124 : PTXReg<"rh124">; +def RH125 : PTXReg<"rh125">; +def RH126 : PTXReg<"rh126">; +def RH127 : PTXReg<"rh127">; -///===- 32-bit Integer Registers ------------------------------------------===// +///===- 32-Bit Registers --------------------------------------------------===// -def R0 : PTXReg<"r0">; -def R1 : PTXReg<"r1">; -def R2 : PTXReg<"r2">; -def R3 : PTXReg<"r3">; -def R4 : PTXReg<"r4">; -def R5 : PTXReg<"r5">; -def R6 : PTXReg<"r6">; -def R7 : PTXReg<"r7">; +def R0 : PTXReg<"r0">; +def R1 : PTXReg<"r1">; +def R2 : PTXReg<"r2">; +def R3 : PTXReg<"r3">; +def R4 : PTXReg<"r4">; +def R5 : PTXReg<"r5">; +def R6 : PTXReg<"r6">; +def R7 : PTXReg<"r7">; +def R8 : PTXReg<"r8">; +def R9 : PTXReg<"r9">; +def R10 : PTXReg<"r10">; +def R11 : PTXReg<"r11">; +def R12 : PTXReg<"r12">; +def R13 : PTXReg<"r13">; +def R14 : PTXReg<"r14">; +def R15 : PTXReg<"r15">; +def R16 : PTXReg<"r16">; +def R17 : PTXReg<"r17">; +def R18 : PTXReg<"r18">; +def R19 : PTXReg<"r19">; +def R20 : PTXReg<"r20">; +def R21 : PTXReg<"r21">; +def R22 : PTXReg<"r22">; +def R23 : PTXReg<"r23">; +def R24 : PTXReg<"r24">; +def R25 : PTXReg<"r25">; +def R26 : PTXReg<"r26">; +def R27 : PTXReg<"r27">; +def R28 : PTXReg<"r28">; +def R29 : PTXReg<"r29">; +def R30 : PTXReg<"r30">; +def R31 : PTXReg<"r31">; +def R32 : PTXReg<"r32">; +def R33 : PTXReg<"r33">; +def R34 : PTXReg<"r34">; +def R35 : PTXReg<"r35">; +def R36 : PTXReg<"r36">; +def R37 : PTXReg<"r37">; +def R38 : PTXReg<"r38">; +def R39 : PTXReg<"r39">; +def R40 : PTXReg<"r40">; +def R41 : PTXReg<"r41">; +def R42 : PTXReg<"r42">; +def R43 : PTXReg<"r43">; +def R44 : PTXReg<"r44">; +def R45 : PTXReg<"r45">; +def R46 : PTXReg<"r46">; +def R47 : PTXReg<"r47">; +def R48 : PTXReg<"r48">; +def R49 : PTXReg<"r49">; +def R50 : PTXReg<"r50">; +def R51 : PTXReg<"r51">; +def R52 : PTXReg<"r52">; +def R53 : PTXReg<"r53">; +def R54 : PTXReg<"r54">; +def R55 : PTXReg<"r55">; +def R56 : PTXReg<"r56">; +def R57 : PTXReg<"r57">; +def R58 : PTXReg<"r58">; +def R59 : PTXReg<"r59">; +def R60 : PTXReg<"r60">; +def R61 : PTXReg<"r61">; +def R62 : PTXReg<"r62">; +def R63 : PTXReg<"r63">; +def R64 : PTXReg<"r64">; +def R65 : PTXReg<"r65">; +def R66 : PTXReg<"r66">; +def R67 : PTXReg<"r67">; +def R68 : PTXReg<"r68">; +def R69 : PTXReg<"r69">; +def R70 : PTXReg<"r70">; +def R71 : PTXReg<"r71">; +def R72 : PTXReg<"r72">; +def R73 : PTXReg<"r73">; +def R74 : PTXReg<"r74">; +def R75 : PTXReg<"r75">; +def R76 : PTXReg<"r76">; +def R77 : PTXReg<"r77">; +def R78 : PTXReg<"r78">; +def R79 : PTXReg<"r79">; +def R80 : PTXReg<"r80">; +def R81 : PTXReg<"r81">; +def R82 : PTXReg<"r82">; +def R83 : PTXReg<"r83">; +def R84 : PTXReg<"r84">; +def R85 : PTXReg<"r85">; +def R86 : PTXReg<"r86">; +def R87 : PTXReg<"r87">; +def R88 : PTXReg<"r88">; +def R89 : PTXReg<"r89">; +def R90 : PTXReg<"r90">; +def R91 : PTXReg<"r91">; +def R92 : PTXReg<"r92">; +def R93 : PTXReg<"r93">; +def R94 : PTXReg<"r94">; +def R95 : PTXReg<"r95">; +def R96 : PTXReg<"r96">; +def R97 : PTXReg<"r97">; +def R98 : PTXReg<"r98">; +def R99 : PTXReg<"r99">; +def R100 : PTXReg<"r100">; +def R101 : PTXReg<"r101">; +def R102 : PTXReg<"r102">; +def R103 : PTXReg<"r103">; +def R104 : PTXReg<"r104">; +def R105 : PTXReg<"r105">; +def R106 : PTXReg<"r106">; +def R107 : PTXReg<"r107">; +def R108 : PTXReg<"r108">; +def R109 : PTXReg<"r109">; +def R110 : PTXReg<"r110">; +def R111 : PTXReg<"r111">; +def R112 : PTXReg<"r112">; +def R113 : PTXReg<"r113">; +def R114 : PTXReg<"r114">; +def R115 : PTXReg<"r115">; +def R116 : PTXReg<"r116">; +def R117 : PTXReg<"r117">; +def R118 : PTXReg<"r118">; +def R119 : PTXReg<"r119">; +def R120 : PTXReg<"r120">; +def R121 : PTXReg<"r121">; +def R122 : PTXReg<"r122">; +def R123 : PTXReg<"r123">; +def R124 : PTXReg<"r124">; +def R125 : PTXReg<"r125">; +def R126 : PTXReg<"r126">; +def R127 : PTXReg<"r127">; -///===- 64-bit Integer Registers ------------------------------------------===// +///===- 64-Bit Registers --------------------------------------------------===// -def RD0 : PTXReg<"rd0">; -def RD1 : PTXReg<"rd1">; -def RD2 : PTXReg<"rd2">; -def RD3 : PTXReg<"rd3">; -def RD4 : PTXReg<"rd4">; -def RD5 : PTXReg<"rd5">; -def RD6 : PTXReg<"rd6">; -def RD7 : PTXReg<"rd7">; +def RD0 : PTXReg<"rd0">; +def RD1 : PTXReg<"rd1">; +def RD2 : PTXReg<"rd2">; +def RD3 : PTXReg<"rd3">; +def RD4 : PTXReg<"rd4">; +def RD5 : PTXReg<"rd5">; +def RD6 : PTXReg<"rd6">; +def RD7 : PTXReg<"rd7">; +def RD8 : PTXReg<"rd8">; +def RD9 : PTXReg<"rd9">; +def RD10 : PTXReg<"rd10">; +def RD11 : PTXReg<"rd11">; +def RD12 : PTXReg<"rd12">; +def RD13 : PTXReg<"rd13">; +def RD14 : PTXReg<"rd14">; +def RD15 : PTXReg<"rd15">; +def RD16 : PTXReg<"rd16">; +def RD17 : PTXReg<"rd17">; +def RD18 : PTXReg<"rd18">; +def RD19 : PTXReg<"rd19">; +def RD20 : PTXReg<"rd20">; +def RD21 : PTXReg<"rd21">; +def RD22 : PTXReg<"rd22">; +def RD23 : PTXReg<"rd23">; +def RD24 : PTXReg<"rd24">; +def RD25 : PTXReg<"rd25">; +def RD26 : PTXReg<"rd26">; +def RD27 : PTXReg<"rd27">; +def RD28 : PTXReg<"rd28">; +def RD29 : PTXReg<"rd29">; +def RD30 : PTXReg<"rd30">; +def RD31 : PTXReg<"rd31">; +def RD32 : PTXReg<"rd32">; +def RD33 : PTXReg<"rd33">; +def RD34 : PTXReg<"rd34">; +def RD35 : PTXReg<"rd35">; +def RD36 : PTXReg<"rd36">; +def RD37 : PTXReg<"rd37">; +def RD38 : PTXReg<"rd38">; +def RD39 : PTXReg<"rd39">; +def RD40 : PTXReg<"rd40">; +def RD41 : PTXReg<"rd41">; +def RD42 : PTXReg<"rd42">; +def RD43 : PTXReg<"rd43">; +def RD44 : PTXReg<"rd44">; +def RD45 : PTXReg<"rd45">; +def RD46 : PTXReg<"rd46">; +def RD47 : PTXReg<"rd47">; +def RD48 : PTXReg<"rd48">; +def RD49 : PTXReg<"rd49">; +def RD50 : PTXReg<"rd50">; +def RD51 : PTXReg<"rd51">; +def RD52 : PTXReg<"rd52">; +def RD53 : PTXReg<"rd53">; +def RD54 : PTXReg<"rd54">; +def RD55 : PTXReg<"rd55">; +def RD56 : PTXReg<"rd56">; +def RD57 : PTXReg<"rd57">; +def RD58 : PTXReg<"rd58">; +def RD59 : PTXReg<"rd59">; +def RD60 : PTXReg<"rd60">; +def RD61 : PTXReg<"rd61">; +def RD62 : PTXReg<"rd62">; +def RD63 : PTXReg<"rd63">; +def RD64 : PTXReg<"rd64">; +def RD65 : PTXReg<"rd65">; +def RD66 : PTXReg<"rd66">; +def RD67 : PTXReg<"rd67">; +def RD68 : PTXReg<"rd68">; +def RD69 : PTXReg<"rd69">; +def RD70 : PTXReg<"rd70">; +def RD71 : PTXReg<"rd71">; +def RD72 : PTXReg<"rd72">; +def RD73 : PTXReg<"rd73">; +def RD74 : PTXReg<"rd74">; +def RD75 : PTXReg<"rd75">; +def RD76 : PTXReg<"rd76">; +def RD77 : PTXReg<"rd77">; +def RD78 : PTXReg<"rd78">; +def RD79 : PTXReg<"rd79">; +def RD80 : PTXReg<"rd80">; +def RD81 : PTXReg<"rd81">; +def RD82 : PTXReg<"rd82">; +def RD83 : PTXReg<"rd83">; +def RD84 : PTXReg<"rd84">; +def RD85 : PTXReg<"rd85">; +def RD86 : PTXReg<"rd86">; +def RD87 : PTXReg<"rd87">; +def RD88 : PTXReg<"rd88">; +def RD89 : PTXReg<"rd89">; +def RD90 : PTXReg<"rd90">; +def RD91 : PTXReg<"rd91">; +def RD92 : PTXReg<"rd92">; +def RD93 : PTXReg<"rd93">; +def RD94 : PTXReg<"rd94">; +def RD95 : PTXReg<"rd95">; +def RD96 : PTXReg<"rd96">; +def RD97 : PTXReg<"rd97">; +def RD98 : PTXReg<"rd98">; +def RD99 : PTXReg<"rd99">; +def RD100 : PTXReg<"rd100">; +def RD101 : PTXReg<"rd101">; +def RD102 : PTXReg<"rd102">; +def RD103 : PTXReg<"rd103">; +def RD104 : PTXReg<"rd104">; +def RD105 : PTXReg<"rd105">; +def RD106 : PTXReg<"rd106">; +def RD107 : PTXReg<"rd107">; +def RD108 : PTXReg<"rd108">; +def RD109 : PTXReg<"rd109">; +def RD110 : PTXReg<"rd110">; +def RD111 : PTXReg<"rd111">; +def RD112 : PTXReg<"rd112">; +def RD113 : PTXReg<"rd113">; +def RD114 : PTXReg<"rd114">; +def RD115 : PTXReg<"rd115">; +def RD116 : PTXReg<"rd116">; +def RD117 : PTXReg<"rd117">; +def RD118 : PTXReg<"rd118">; +def RD119 : PTXReg<"rd119">; +def RD120 : PTXReg<"rd120">; +def RD121 : PTXReg<"rd121">; +def RD122 : PTXReg<"rd122">; +def RD123 : PTXReg<"rd123">; +def RD124 : PTXReg<"rd124">; +def RD125 : PTXReg<"rd125">; +def RD126 : PTXReg<"rd126">; +def RD127 : PTXReg<"rd127">; //===----------------------------------------------------------------------===// // Register classes //===----------------------------------------------------------------------===// - -def RegPred : RegisterClass<"PTX", [i1], 8, (sequence "P%u", 0, 7)>; -def RegI16 : RegisterClass<"PTX", [i16], 16, (sequence "RH%u", 0, 7)>; -def RegI32 : RegisterClass<"PTX", [i32], 32, (sequence "R%u", 0, 7)>; -def RegI64 : RegisterClass<"PTX", [i64], 64, (sequence "RD%u", 0, 7)>; -def RegF32 : RegisterClass<"PTX", [f32], 32, (sequence "R%u", 0, 7)>; -def RegF64 : RegisterClass<"PTX", [f64], 64, (sequence "RD%u", 0, 7)>; +def RegPred : RegisterClass<"PTX", [i1], 8, (sequence "P%u", 0, 127)>; +def RegI16 : RegisterClass<"PTX", [i16], 16, (sequence "RH%u", 0, 127)>; +def RegI32 : RegisterClass<"PTX", [i32], 32, (sequence "R%u", 0, 127)>; +def RegI64 : RegisterClass<"PTX", [i64], 64, (sequence "RD%u", 0, 127)>; +def RegF32 : RegisterClass<"PTX", [f32], 32, (sequence "R%u", 0, 127)>; +def RegF64 : RegisterClass<"PTX", [f64], 64, (sequence "RD%u", 0, 127)>; diff --git a/lib/Target/PTX/generate-register-td.py b/lib/Target/PTX/generate-register-td.py new file mode 100755 index 0000000..1528690 --- /dev/null +++ b/lib/Target/PTX/generate-register-td.py @@ -0,0 +1,163 @@ +#!/usr/bin/env python +##===- generate-register-td.py --------------------------------*-python-*--===## +## +## The LLVM Compiler Infrastructure +## +## This file is distributed under the University of Illinois Open Source +## License. See LICENSE.TXT for details. +## +##===----------------------------------------------------------------------===## +## +## This file describes the PTX register file generator. +## +##===----------------------------------------------------------------------===## + +from sys import argv, exit, stdout + + +if len(argv) != 5: + print('Usage: generate-register-td.py ') + exit(1) + +try: + num_pred = int(argv[1]) + num_16bit = int(argv[2]) + num_32bit = int(argv[3]) + num_64bit = int(argv[4]) +except: + print('ERROR: Invalid integer parameter') + exit(1) + +## Print the register definition file +td_file = open('PTXRegisterInfo.td', 'w') + +td_file.write(''' +//===- PTXRegisterInfo.td - PTX Register defs ----------------*- tblgen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Declarations that describe the PTX register file +//===----------------------------------------------------------------------===// + +class PTXReg : Register { + let Namespace = "PTX"; +} + +//===----------------------------------------------------------------------===// +// Registers +//===----------------------------------------------------------------------===// +''') + + +# Print predicate registers +td_file.write('\n///===- Predicate Registers -----------------------------------------------===//\n\n') +for r in range(0, num_pred): + td_file.write('def P%d : PTXReg<"p%d">;\n' % (r, r)) + +# Print 16-bit registers +td_file.write('\n///===- 16-Bit Registers --------------------------------------------------===//\n\n') +for r in range(0, num_16bit): + td_file.write('def RH%d : PTXReg<"rh%d">;\n' % (r, r)) + +# Print 32-bit registers +td_file.write('\n///===- 32-Bit Registers --------------------------------------------------===//\n\n') +for r in range(0, num_32bit): + td_file.write('def R%d : PTXReg<"r%d">;\n' % (r, r)) + +# Print 64-bit registers +td_file.write('\n///===- 64-Bit Registers --------------------------------------------------===//\n\n') +for r in range(0, num_64bit): + td_file.write('def RD%d : PTXReg<"rd%d">;\n' % (r, r)) + + +td_file.write(''' +//===----------------------------------------------------------------------===// +// Register classes +//===----------------------------------------------------------------------===// +''') + + +# Print register classes + +td_file.write('def RegPred : RegisterClass<"PTX", [i1], 8, (sequence "P%%u", 0, %d)>;\n' % (num_pred-1)) +td_file.write('def RegI16 : RegisterClass<"PTX", [i16], 16, (sequence "RH%%u", 0, %d)>;\n' % (num_16bit-1)) +td_file.write('def RegI32 : RegisterClass<"PTX", [i32], 32, (sequence "R%%u", 0, %d)>;\n' % (num_32bit-1)) +td_file.write('def RegI64 : RegisterClass<"PTX", [i64], 64, (sequence "RD%%u", 0, %d)>;\n' % (num_64bit-1)) +td_file.write('def RegF32 : RegisterClass<"PTX", [f32], 32, (sequence "R%%u", 0, %d)>;\n' % (num_32bit-1)) +td_file.write('def RegF64 : RegisterClass<"PTX", [f64], 64, (sequence "RD%%u", 0, %d)>;\n' % (num_64bit-1)) + + +td_file.close() + +## Now write the PTXCallingConv.td file +td_file = open('PTXCallingConv.td', 'w') + +# Reserve 10% of the available registers for return values, and the other 90% +# for parameters +num_ret_pred = int(0.1 * num_pred) +num_ret_16bit = int(0.1 * num_16bit) +num_ret_32bit = int(0.1 * num_32bit) +num_ret_64bit = int(0.1 * num_64bit) +num_param_pred = num_pred - num_ret_pred +num_param_16bit = num_16bit - num_ret_16bit +num_param_32bit = num_32bit - num_ret_32bit +num_param_64bit = num_64bit - num_ret_64bit + +param_regs_pred = [('P%d' % (i+num_ret_pred)) for i in range(0, num_param_pred)] +ret_regs_pred = ['P%d' % i for i in range(0, num_ret_pred)] +param_regs_16bit = [('RH%d' % (i+num_ret_16bit)) for i in range(0, num_param_16bit)] +ret_regs_16bit = ['RH%d' % i for i in range(0, num_ret_16bit)] +param_regs_32bit = [('R%d' % (i+num_ret_32bit)) for i in range(0, num_param_32bit)] +ret_regs_32bit = ['R%d' % i for i in range(0, num_ret_32bit)] +param_regs_64bit = [('RD%d' % (i+num_ret_64bit)) for i in range(0, num_param_64bit)] +ret_regs_64bit = ['RD%d' % i for i in range(0, num_ret_64bit)] + +param_list_pred = reduce(lambda x, y: '%s, %s' % (x, y), param_regs_pred) +ret_list_pred = reduce(lambda x, y: '%s, %s' % (x, y), ret_regs_pred) +param_list_16bit = reduce(lambda x, y: '%s, %s' % (x, y), param_regs_16bit) +ret_list_16bit = reduce(lambda x, y: '%s, %s' % (x, y), ret_regs_16bit) +param_list_32bit = reduce(lambda x, y: '%s, %s' % (x, y), param_regs_32bit) +ret_list_32bit = reduce(lambda x, y: '%s, %s' % (x, y), ret_regs_32bit) +param_list_64bit = reduce(lambda x, y: '%s, %s' % (x, y), param_regs_64bit) +ret_list_64bit = reduce(lambda x, y: '%s, %s' % (x, y), ret_regs_64bit) + +td_file.write(''' +//===--- PTXCallingConv.td - Calling Conventions -----------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This describes the calling conventions for the PTX architecture. +// +//===----------------------------------------------------------------------===// + +// PTX Formal Parameter Calling Convention +def CC_PTX : CallingConv<[ + CCIfType<[i1], CCAssignToReg<[%s]>>, + CCIfType<[i16], CCAssignToReg<[%s]>>, + CCIfType<[i32,f32], CCAssignToReg<[%s]>>, + CCIfType<[i64,f64], CCAssignToReg<[%s]>> +]>; + +// PTX Return Value Calling Convention +def RetCC_PTX : CallingConv<[ + CCIfType<[i1], CCAssignToReg<[%s]>>, + CCIfType<[i16], CCAssignToReg<[%s]>>, + CCIfType<[i32,f32], CCAssignToReg<[%s]>>, + CCIfType<[i64,f64], CCAssignToReg<[%s]>> +]>; +''' % (param_list_pred, param_list_16bit, param_list_32bit, param_list_64bit, + ret_list_pred, ret_list_16bit, ret_list_32bit, ret_list_64bit)) + + +td_file.close() diff --git a/test/CodeGen/PTX/add.ll b/test/CodeGen/PTX/add.ll index c16be49..293aebe 100644 --- a/test/CodeGen/PTX/add.ll +++ b/test/CodeGen/PTX/add.ll @@ -1,70 +1,70 @@ ; RUN: llc < %s -march=ptx32 | FileCheck %s define ptx_device i16 @t1_u16(i16 %x, i16 %y) { -; CHECK: add.u16 rh0, rh1, rh2; +; CHECK: add.u16 rh{{[0-9]+}}, rh{{[0-9]+}}, rh{{[0-9]+}}; ; CHECK-NEXT: ret; %z = add i16 %x, %y ret i16 %z } define ptx_device i32 @t1_u32(i32 %x, i32 %y) { -; CHECK: add.u32 r0, r1, r2; +; CHECK: add.u32 r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}; ; CHECK-NEXT: ret; %z = add i32 %x, %y ret i32 %z } define ptx_device i64 @t1_u64(i64 %x, i64 %y) { -; CHECK: add.u64 rd0, rd1, rd2; +; CHECK: add.u64 rd{{[0-9]+}}, rd{{[0-9]+}}, rd{{[0-9]+}}; ; CHECK-NEXT: ret; %z = add i64 %x, %y ret i64 %z } define ptx_device float @t1_f32(float %x, float %y) { -; CHECK: add.rn.f32 r0, r1, r2 +; CHECK: add.rn.f32 r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}} ; CHECK-NEXT: ret; %z = fadd float %x, %y ret float %z } define ptx_device double @t1_f64(double %x, double %y) { -; CHECK: add.rn.f64 rd0, rd1, rd2 +; CHECK: add.rn.f64 rd{{[0-9]+}}, rd{{[0-9]+}}, rd{{[0-9]+}} ; CHECK-NEXT: ret; %z = fadd double %x, %y ret double %z } define ptx_device i16 @t2_u16(i16 %x) { -; CHECK: add.u16 rh0, rh1, 1; +; CHECK: add.u16 rh{{[0-9]+}}, rh{{[0-9]+}}, 1; ; CHECK-NEXT: ret; %z = add i16 %x, 1 ret i16 %z } define ptx_device i32 @t2_u32(i32 %x) { -; CHECK: add.u32 r0, r1, 1; +; CHECK: add.u32 r{{[0-9]+}}, r{{[0-9]+}}, 1; ; CHECK-NEXT: ret; %z = add i32 %x, 1 ret i32 %z } define ptx_device i64 @t2_u64(i64 %x) { -; CHECK: add.u64 rd0, rd1, 1; +; CHECK: add.u64 rd{{[0-9]+}}, rd{{[0-9]+}}, 1; ; CHECK-NEXT: ret; %z = add i64 %x, 1 ret i64 %z } define ptx_device float @t2_f32(float %x) { -; CHECK: add.rn.f32 r0, r1, 0F3F800000; +; CHECK: add.rn.f32 r{{[0-9]+}}, r{{[0-9]+}}, 0F3F800000; ; CHECK-NEXT: ret; %z = fadd float %x, 1.0 ret float %z } define ptx_device double @t2_f64(double %x) { -; CHECK: add.rn.f64 rd0, rd1, 0D3FF0000000000000; +; CHECK: add.rn.f64 rd{{[0-9]+}}, rd{{[0-9]+}}, 0D3FF0000000000000; ; CHECK-NEXT: ret; %z = fadd double %x, 1.0 ret double %z diff --git a/test/CodeGen/PTX/aggregates.ll b/test/CodeGen/PTX/aggregates.ll new file mode 100644 index 0000000..23f28a7 --- /dev/null +++ b/test/CodeGen/PTX/aggregates.ll @@ -0,0 +1,23 @@ +; RUN: llc < %s -march=ptx32 -mattr=sm20 | FileCheck %s + +%complex = type { float, float } + +define ptx_device %complex @complex_add(%complex %a, %complex %b) { +entry: +; CHECK: ld.param.f32 r[[R0:[0-9]+]], [__param_1]; +; CHECK-NEXT: ld.param.f32 r[[R2:[0-9]+]], [__param_3]; +; CHECK-NEXT: ld.param.f32 r[[R1:[0-9]+]], [__param_2]; +; CHECK-NEXT: ld.param.f32 r[[R3:[0-9]+]], [__param_4]; +; CHECK-NEXT: add.rn.f32 r[[R0]], r[[R0]], r[[R2]]; +; CHECK-NEXT: add.rn.f32 r[[R1]], r[[R1]], r[[R3]]; +; CHECK-NEXT: ret; + %a.real = extractvalue %complex %a, 0 + %a.imag = extractvalue %complex %a, 1 + %b.real = extractvalue %complex %b, 0 + %b.imag = extractvalue %complex %b, 1 + %ret.real = fadd float %a.real, %b.real + %ret.imag = fadd float %a.imag, %b.imag + %ret.0 = insertvalue %complex undef, float %ret.real, 0 + %ret.1 = insertvalue %complex %ret.0, float %ret.imag, 1 + ret %complex %ret.1 +} diff --git a/test/CodeGen/PTX/bitwise.ll b/test/CodeGen/PTX/bitwise.ll index dbc77e5..3859280 100644 --- a/test/CodeGen/PTX/bitwise.ll +++ b/test/CodeGen/PTX/bitwise.ll @@ -3,21 +3,21 @@ ; preds define ptx_device i32 @t1_and_preds(i1 %x, i1 %y) { -; CHECK: and.pred p0, p1, p2 +; CHECK: and.pred p{{[0-9]+}}, p{{[0-9]+}}, p{{[0-9]+}} %c = and i1 %x, %y %d = zext i1 %c to i32 ret i32 %d } define ptx_device i32 @t1_or_preds(i1 %x, i1 %y) { -; CHECK: or.pred p0, p1, p2 +; CHECK: or.pred p{{[0-9]+}}, p{{[0-9]+}}, p{{[0-9]+}} %a = or i1 %x, %y %b = zext i1 %a to i32 ret i32 %b } define ptx_device i32 @t1_xor_preds(i1 %x, i1 %y) { -; CHECK: xor.pred p0, p1, p2 +; CHECK: xor.pred p{{[0-9]+}}, p{{[0-9]+}}, p{{[0-9]+}} %a = xor i1 %x, %y %b = zext i1 %a to i32 ret i32 %b diff --git a/test/CodeGen/PTX/bra.ll b/test/CodeGen/PTX/bra.ll index 49383eb..7cc9444 100644 --- a/test/CodeGen/PTX/bra.ll +++ b/test/CodeGen/PTX/bra.ll @@ -10,15 +10,15 @@ loop: define ptx_device i32 @test_bra_cond_direct(i32 %x, i32 %y) { entry: -; CHECK: setp.le.u32 p0, r1, r2 +; CHECK: setp.le.u32 p0, r[[R0:[0-9]+]], r[[R1:[0-9]+]] %p = icmp ugt i32 %x, %y ; CHECK-NEXT: @p0 bra ; CHECK-NOT: bra br i1 %p, label %clause.if, label %clause.else clause.if: -; CHECK: mov.u32 r0, r1 +; CHECK: mov.u32 r{{[0-9]+}}, r[[R0]] ret i32 %x clause.else: -; CHECK: mov.u32 r0, r2 +; CHECK: mov.u32 r{{[0-9]+}}, r[[R1]] ret i32 %y } diff --git a/test/CodeGen/PTX/cvt.ll b/test/CodeGen/PTX/cvt.ll index f723369..18f7ef3 100644 --- a/test/CodeGen/PTX/cvt.ll +++ b/test/CodeGen/PTX/cvt.ll @@ -4,9 +4,9 @@ ; (note: we convert back to i32 to return) define ptx_device i32 @cvt_pred_i16(i16 %x, i1 %y) { -; CHECK: setp.gt.b16 p0, rh1, 0 -; CHECK-NEXT: and.pred p0, p0, p1; -; CHECK-NEXT: selp.u32 r0, 1, 0, p0; +; CHECK: setp.gt.b16 p[[P0:[0-9]+]], rh{{[0-9]+}}, 0 +; CHECK-NEXT: and.pred p0, p[[P0:[0-9]+]], p{{[0-9]+}}; +; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0:[0-9]+]]; ; CHECK-NEXT: ret; %a = trunc i16 %x to i1 %b = and i1 %a, %y @@ -15,9 +15,9 @@ define ptx_device i32 @cvt_pred_i16(i16 %x, i1 %y) { } define ptx_device i32 @cvt_pred_i32(i32 %x, i1 %y) { -; CHECK: setp.gt.b32 p0, r1, 0 -; CHECK-NEXT: and.pred p0, p0, p1; -; CHECK-NEXT: selp.u32 r0, 1, 0, p0; +; CHECK: setp.gt.b32 p[[P0:[0-9]+]], r{{[0-9]+}}, 0 +; CHECK-NEXT: and.pred p0, p[[P0:[0-9]+]], p{{[0-9]+}}; +; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0:[0-9]+]]; ; CHECK-NEXT: ret; %a = trunc i32 %x to i1 %b = and i1 %a, %y @@ -26,9 +26,9 @@ define ptx_device i32 @cvt_pred_i32(i32 %x, i1 %y) { } define ptx_device i32 @cvt_pred_i64(i64 %x, i1 %y) { -; CHECK: setp.gt.b64 p0, rd1, 0 -; CHECK-NEXT: and.pred p0, p0, p1; -; CHECK-NEXT: selp.u32 r0, 1, 0, p0; +; CHECK: setp.gt.b64 p[[P0:[0-9]+]], rd{{[0-9]+}}, 0 +; CHECK-NEXT: and.pred p0, p[[P0:[0-9]+]], p{{[0-9]+}}; +; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0:[0-9]+]]; ; CHECK-NEXT: ret; %a = trunc i64 %x to i1 %b = and i1 %a, %y @@ -37,9 +37,9 @@ define ptx_device i32 @cvt_pred_i64(i64 %x, i1 %y) { } define ptx_device i32 @cvt_pred_f32(float %x, i1 %y) { -; CHECK: setp.gt.b32 p0, r1, 0 -; CHECK-NEXT: and.pred p0, p0, p1; -; CHECK-NEXT: selp.u32 r0, 1, 0, p0; +; CHECK: setp.gt.b32 p[[P0:[0-9]+]], r{{[0-9]+}}, 0 +; CHECK-NEXT: and.pred p0, p[[P0:[0-9]+]], p{{[0-9]+}}; +; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0:[0-9]+]]; ; CHECK-NEXT: ret; %a = fptoui float %x to i1 %b = and i1 %a, %y @@ -48,9 +48,9 @@ define ptx_device i32 @cvt_pred_f32(float %x, i1 %y) { } define ptx_device i32 @cvt_pred_f64(double %x, i1 %y) { -; CHECK: setp.gt.b64 p0, rd1, 0 -; CHECK-NEXT: and.pred p0, p0, p1; -; CHECK-NEXT: selp.u32 r0, 1, 0, p0; +; CHECK: setp.gt.b64 p[[P0:[0-9]+]], rd{{[0-9]+}}, 0 +; CHECK-NEXT: and.pred p0, p[[P0:[0-9]+]], p{{[0-9]+}}; +; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0:[0-9]+]]; ; CHECK-NEXT: ret; %a = fptoui double %x to i1 %b = and i1 %a, %y @@ -61,35 +61,35 @@ define ptx_device i32 @cvt_pred_f64(double %x, i1 %y) { ; i16 define ptx_device i16 @cvt_i16_preds(i1 %x) { -; CHECK: selp.u16 rh0, 1, 0, p1; +; CHECK: selp.u16 rh{{[0-9]+}}, 1, 0, p{{[0-9]+}}; ; CHECK-NEXT: ret; %a = zext i1 %x to i16 ret i16 %a } define ptx_device i16 @cvt_i16_i32(i32 %x) { -; CHECK: cvt.u16.u32 rh0, r1; +; CHECK: cvt.u16.u32 rh{{[0-9]+}}, r{{[0-9]+}}; ; CHECK-NEXT: ret; %a = trunc i32 %x to i16 ret i16 %a } define ptx_device i16 @cvt_i16_i64(i64 %x) { -; CHECK: cvt.u16.u64 rh0, rd1; +; CHECK: cvt.u16.u64 rh{{[0-9]+}}, rd{{[0-9]+}}; ; CHECK-NEXT: ret; %a = trunc i64 %x to i16 ret i16 %a } define ptx_device i16 @cvt_i16_f32(float %x) { -; CHECK: cvt.rzi.u16.f32 rh0, r1; +; CHECK: cvt.rzi.u16.f32 rh{{[0-9]+}}, r{{[0-9]+}}; ; CHECK-NEXT: ret; %a = fptoui float %x to i16 ret i16 %a } define ptx_device i16 @cvt_i16_f64(double %x) { -; CHECK: cvt.rzi.u16.f64 rh0, rd1; +; CHECK: cvt.rzi.u16.f64 rh{{[0-9]+}}, rd{{[0-9]+}}; ; CHECK-NEXT: ret; %a = fptoui double %x to i16 ret i16 %a @@ -98,35 +98,35 @@ define ptx_device i16 @cvt_i16_f64(double %x) { ; i32 define ptx_device i32 @cvt_i32_preds(i1 %x) { -; CHECK: selp.u32 r0, 1, 0, p1; +; CHECK: selp.u32 r{{[0-9]+}}, 1, 0, p{{[0-9]+}}; ; CHECK-NEXT: ret; %a = zext i1 %x to i32 ret i32 %a } define ptx_device i32 @cvt_i32_i16(i16 %x) { -; CHECK: cvt.u32.u16 r0, rh1; +; CHECK: cvt.u32.u16 r{{[0-9]+}}, rh{{[0-9]+}}; ; CHECK-NEXT: ret; %a = zext i16 %x to i32 ret i32 %a } define ptx_device i32 @cvt_i32_i64(i64 %x) { -; CHECK: cvt.u32.u64 r0, rd1; +; CHECK: cvt.u32.u64 r{{[0-9]+}}, rd{{[0-9]+}}; ; CHECK-NEXT: ret; %a = trunc i64 %x to i32 ret i32 %a } define ptx_device i32 @cvt_i32_f32(float %x) { -; CHECK: cvt.rzi.u32.f32 r0, r1; +; CHECK: cvt.rzi.u32.f32 r{{[0-9]+}}, r{{[0-9]+}}; ; CHECK-NEXT: ret; %a = fptoui float %x to i32 ret i32 %a } define ptx_device i32 @cvt_i32_f64(double %x) { -; CHECK: cvt.rzi.u32.f64 r0, rd1; +; CHECK: cvt.rzi.u32.f64 r{{[0-9]+}}, rd{{[0-9]+}}; ; CHECK-NEXT: ret; %a = fptoui double %x to i32 ret i32 %a @@ -135,35 +135,35 @@ define ptx_device i32 @cvt_i32_f64(double %x) { ; i64 define ptx_device i64 @cvt_i64_preds(i1 %x) { -; CHECK: selp.u64 rd0, 1, 0, p1; +; CHECK: selp.u64 rd{{[0-9]+}}, 1, 0, p{{[0-9]+}}; ; CHECK-NEXT: ret; %a = zext i1 %x to i64 ret i64 %a } define ptx_device i64 @cvt_i64_i16(i16 %x) { -; CHECK: cvt.u64.u16 rd0, rh1; +; CHECK: cvt.u64.u16 rd{{[0-9]+}}, rh{{[0-9]+}}; ; CHECK-NEXT: ret; %a = zext i16 %x to i64 ret i64 %a } define ptx_device i64 @cvt_i64_i32(i32 %x) { -; CHECK: cvt.u64.u32 rd0, r1; +; CHECK: cvt.u64.u32 rd{{[0-9]+}}, r{{[0-9]+}}; ; CHECK-NEXT: ret; %a = zext i32 %x to i64 ret i64 %a } define ptx_device i64 @cvt_i64_f32(float %x) { -; CHECK: cvt.rzi.u64.f32 rd0, r1; +; CHECK: cvt.rzi.u64.f32 rd{{[0-9]+}}, r{{[0-9]+}}; ; CHECK-NEXT: ret; %a = fptoui float %x to i64 ret i64 %a } define ptx_device i64 @cvt_i64_f64(double %x) { -; CHECK: cvt.rzi.u64.f64 rd0, rd1; +; CHECK: cvt.rzi.u64.f64 rd{{[0-9]+}}, rd{{[0-9]+}}; ; CHECK: ret; %a = fptoui double %x to i64 ret i64 %a @@ -172,35 +172,35 @@ define ptx_device i64 @cvt_i64_f64(double %x) { ; f32 define ptx_device float @cvt_f32_preds(i1 %x) { -; CHECK: selp.f32 r0, 0F3F800000, 0F00000000, p1; +; CHECK: selp.f32 r{{[0-9]+}}, 0F3F800000, 0F00000000, p{{[0-9]+}}; ; CHECK-NEXT: ret; %a = uitofp i1 %x to float ret float %a } define ptx_device float @cvt_f32_i16(i16 %x) { -; CHECK: cvt.rn.f32.u16 r0, rh1; +; CHECK: cvt.rn.f32.u16 r{{[0-9]+}}, rh{{[0-9]+}}; ; CHECK-NEXT: ret; %a = uitofp i16 %x to float ret float %a } define ptx_device float @cvt_f32_i32(i32 %x) { -; CHECK: cvt.rn.f32.u32 r0, r1; +; CHECK: cvt.rn.f32.u32 r{{[0-9]+}}, r{{[0-9]+}}; ; CHECK-NEXT: ret; %a = uitofp i32 %x to float ret float %a } define ptx_device float @cvt_f32_i64(i64 %x) { -; CHECK: cvt.rn.f32.u64 r0, rd1; +; CHECK: cvt.rn.f32.u64 r{{[0-9]+}}, rd{{[0-9]+}}; ; CHECK-NEXT: ret; %a = uitofp i64 %x to float ret float %a } define ptx_device float @cvt_f32_f64(double %x) { -; CHECK: cvt.rn.f32.f64 r0, rd1; +; CHECK: cvt.rn.f32.f64 r{{[0-9]+}}, rd{{[0-9]+}}; ; CHECK-NEXT: ret; %a = fptrunc double %x to float ret float %a @@ -209,35 +209,35 @@ define ptx_device float @cvt_f32_f64(double %x) { ; f64 define ptx_device double @cvt_f64_preds(i1 %x) { -; CHECK: selp.f64 rd0, 0D3F80000000000000, 0D0000000000000000, p1; +; CHECK: selp.f64 rd{{[0-9]+}}, 0D3F80000000000000, 0D0000000000000000, p{{[0-9]+}}; ; CHECK-NEXT: ret; %a = uitofp i1 %x to double ret double %a } define ptx_device double @cvt_f64_i16(i16 %x) { -; CHECK: cvt.rn.f64.u16 rd0, rh1; +; CHECK: cvt.rn.f64.u16 rd{{[0-9]+}}, rh{{[0-9]+}}; ; CHECK-NEXT: ret; %a = uitofp i16 %x to double ret double %a } define ptx_device double @cvt_f64_i32(i32 %x) { -; CHECK: cvt.rn.f64.u32 rd0, r1; +; CHECK: cvt.rn.f64.u32 rd{{[0-9]+}}, r{{[0-9]+}}; ; CHECK-NEXT: ret; %a = uitofp i32 %x to double ret double %a } define ptx_device double @cvt_f64_i64(i64 %x) { -; CHECK: cvt.rn.f64.u64 rd0, rd1; +; CHECK: cvt.rn.f64.u64 rd{{[0-9]+}}, rd{{[0-9]+}}; ; CHECK-NEXT: ret; %a = uitofp i64 %x to double ret double %a } define ptx_device double @cvt_f64_f32(float %x) { -; CHECK: cvt.f64.f32 rd0, r1; +; CHECK: cvt.f64.f32 rd{{[0-9]+}}, r{{[0-9]+}}; ; CHECK-NEXT: ret; %a = fpext float %x to double ret double %a diff --git a/test/CodeGen/PTX/fdiv-sm10.ll b/test/CodeGen/PTX/fdiv-sm10.ll index eb32222..049d891 100644 --- a/test/CodeGen/PTX/fdiv-sm10.ll +++ b/test/CodeGen/PTX/fdiv-sm10.ll @@ -1,14 +1,14 @@ ; RUN: llc < %s -march=ptx32 -mattr=+sm10 | FileCheck %s define ptx_device float @t1_f32(float %x, float %y) { -; CHECK: div.f32 r0, r1, r2; +; CHECK: div.f32 r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}; ; CHECK-NEXT: ret; %a = fdiv float %x, %y ret float %a } define ptx_device double @t1_f64(double %x, double %y) { -; CHECK: div.f64 rd0, rd1, rd2; +; CHECK: div.f64 rd{{[0-9]+}}, rd{{[0-9]+}}, rd{{[0-9]+}}; ; CHECK-NEXT: ret; %a = fdiv double %x, %y ret double %a diff --git a/test/CodeGen/PTX/fdiv-sm13.ll b/test/CodeGen/PTX/fdiv-sm13.ll index ad24f35..2d95339 100644 --- a/test/CodeGen/PTX/fdiv-sm13.ll +++ b/test/CodeGen/PTX/fdiv-sm13.ll @@ -1,14 +1,14 @@ ; RUN: llc < %s -march=ptx32 -mattr=+sm13 | FileCheck %s define ptx_device float @t1_f32(float %x, float %y) { -; CHECK: div.rn.f32 r0, r1, r2; +; CHECK: div.rn.f32 r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}; ; CHECK-NEXT: ret; %a = fdiv float %x, %y ret float %a } define ptx_device double @t1_f64(double %x, double %y) { -; CHECK: div.rn.f64 rd0, rd1, rd2; +; CHECK: div.rn.f64 rd{{[0-9]+}}, rd{{[0-9]+}}, rd{{[0-9]+}}; ; CHECK-NEXT: ret; %a = fdiv double %x, %y ret double %a diff --git a/test/CodeGen/PTX/fneg.ll b/test/CodeGen/PTX/fneg.ll index 185c37c..66ca74a 100644 --- a/test/CodeGen/PTX/fneg.ll +++ b/test/CodeGen/PTX/fneg.ll @@ -1,14 +1,14 @@ ; RUN: llc < %s -march=ptx32 | FileCheck %s define ptx_device float @t1_f32(float %x) { -; CHECK: neg.f32 r0, r1; +; CHECK: neg.f32 r{{[0-9]+}}, r{{[0-9]+}}; ; CHECK-NEXT: ret; %y = fsub float -0.000000e+00, %x ret float %y } define ptx_device double @t1_f64(double %x) { -; CHECK: neg.f64 rd0, rd1; +; CHECK: neg.f64 rd{{[0-9]+}}, rd{{[0-9]+}}; ; CHECK-NEXT: ret; %y = fsub double -0.000000e+00, %x ret double %y diff --git a/test/CodeGen/PTX/ld.ll b/test/CodeGen/PTX/ld.ll index 9b75998..d184d12 100644 --- a/test/CodeGen/PTX/ld.ll +++ b/test/CodeGen/PTX/ld.ll @@ -63,7 +63,7 @@ define ptx_device i16 @t1_u16(i16* %p) { entry: -;CHECK: ld.global.u16 rh0, [r1]; +;CHECK: ld.global.u16 rh{{[0-9]+}}, [r{{[0-9]+}}]; ;CHECK-NEXT: ret; %x = load i16* %p ret i16 %x @@ -71,7 +71,7 @@ entry: define ptx_device i32 @t1_u32(i32* %p) { entry: -;CHECK: ld.global.u32 r0, [r1]; +;CHECK: ld.global.u32 r{{[0-9]+}}, [r{{[0-9]+}}]; ;CHECK-NEXT: ret; %x = load i32* %p ret i32 %x @@ -79,7 +79,7 @@ entry: define ptx_device i64 @t1_u64(i64* %p) { entry: -;CHECK: ld.global.u64 rd0, [r1]; +;CHECK: ld.global.u64 rd{{[0-9]+}}, [r{{[0-9]+}}]; ;CHECK-NEXT: ret; %x = load i64* %p ret i64 %x @@ -87,7 +87,7 @@ entry: define ptx_device float @t1_f32(float* %p) { entry: -;CHECK: ld.global.f32 r0, [r1]; +;CHECK: ld.global.f32 r{{[0-9]+}}, [r{{[0-9]+}}]; ;CHECK-NEXT: ret; %x = load float* %p ret float %x @@ -95,7 +95,7 @@ entry: define ptx_device double @t1_f64(double* %p) { entry: -;CHECK: ld.global.f64 rd0, [r1]; +;CHECK: ld.global.f64 rd{{[0-9]+}}, [r{{[0-9]+}}]; ;CHECK-NEXT: ret; %x = load double* %p ret double %x @@ -103,7 +103,7 @@ entry: define ptx_device i16 @t2_u16(i16* %p) { entry: -;CHECK: ld.global.u16 rh0, [r1+2]; +;CHECK: ld.global.u16 rh{{[0-9]+}}, [r{{[0-9]+}}+2]; ;CHECK-NEXT: ret; %i = getelementptr i16* %p, i32 1 %x = load i16* %i @@ -112,7 +112,7 @@ entry: define ptx_device i32 @t2_u32(i32* %p) { entry: -;CHECK: ld.global.u32 r0, [r1+4]; +;CHECK: ld.global.u32 r{{[0-9]+}}, [r{{[0-9]+}}+4]; ;CHECK-NEXT: ret; %i = getelementptr i32* %p, i32 1 %x = load i32* %i @@ -121,7 +121,7 @@ entry: define ptx_device i64 @t2_u64(i64* %p) { entry: -;CHECK: ld.global.u64 rd0, [r1+8]; +;CHECK: ld.global.u64 rd{{[0-9]+}}, [r{{[0-9]+}}+8]; ;CHECK-NEXT: ret; %i = getelementptr i64* %p, i32 1 %x = load i64* %i @@ -130,7 +130,7 @@ entry: define ptx_device float @t2_f32(float* %p) { entry: -;CHECK: ld.global.f32 r0, [r1+4]; +;CHECK: ld.global.f32 r{{[0-9]+}}, [r{{[0-9]+}}+4]; ;CHECK-NEXT: ret; %i = getelementptr float* %p, i32 1 %x = load float* %i @@ -139,7 +139,7 @@ entry: define ptx_device double @t2_f64(double* %p) { entry: -;CHECK: ld.global.f64 rd0, [r1+8]; +;CHECK: ld.global.f64 rd{{[0-9]+}}, [r{{[0-9]+}}+8]; ;CHECK-NEXT: ret; %i = getelementptr double* %p, i32 1 %x = load double* %i @@ -148,9 +148,9 @@ entry: define ptx_device i16 @t3_u16(i16* %p, i32 %q) { entry: -;CHECK: shl.b32 r0, r2, 1; -;CHECK-NEXT: add.u32 r0, r1, r0; -;CHECK-NEXT: ld.global.u16 rh0, [r0]; +;CHECK: shl.b32 r[[R0:[0-9]+]], r{{[0-9]+}}, 1; +;CHECK-NEXT: add.u32 r[[R0]], r{{[0-9]+}}, r[[R0]]; +;CHECK-NEXT: ld.global.u16 rh{{[0-9]+}}, [r[[R0]]]; %i = getelementptr i16* %p, i32 %q %x = load i16* %i ret i16 %x @@ -158,9 +158,9 @@ entry: define ptx_device i32 @t3_u32(i32* %p, i32 %q) { entry: -;CHECK: shl.b32 r0, r2, 2; -;CHECK-NEXT: add.u32 r0, r1, r0; -;CHECK-NEXT: ld.global.u32 r0, [r0]; +;CHECK: shl.b32 r[[R0:[0-9]+]], r{{[0-9]+}}, 2; +;CHECK-NEXT: add.u32 r[[R0]], r{{[0-9]+}}, r[[R0]]; +;CHECK-NEXT: ld.global.u32 r{{[0-9]+}}, [r[[R0]]]; %i = getelementptr i32* %p, i32 %q %x = load i32* %i ret i32 %x @@ -168,9 +168,9 @@ entry: define ptx_device i64 @t3_u64(i64* %p, i32 %q) { entry: -;CHECK: shl.b32 r0, r2, 3; -;CHECK-NEXT: add.u32 r0, r1, r0; -;CHECK-NEXT: ld.global.u64 rd0, [r0]; +;CHECK: shl.b32 r[[R0:[0-9]+]], r{{[0-9]+}}, 3; +;CHECK-NEXT: add.u32 r[[R0]], r{{[0-9]+}}, r[[R0]]; +;CHECK-NEXT: ld.global.u64 rd{{[0-9]+}}, [r[[R0]]]; %i = getelementptr i64* %p, i32 %q %x = load i64* %i ret i64 %x @@ -178,9 +178,9 @@ entry: define ptx_device float @t3_f32(float* %p, i32 %q) { entry: -;CHECK: shl.b32 r0, r2, 2; -;CHECK-NEXT: add.u32 r0, r1, r0; -;CHECK-NEXT: ld.global.f32 r0, [r0]; +;CHECK: shl.b32 r[[R0:[0-9]+]], r{{[0-9]+}}, 2; +;CHECK-NEXT: add.u32 r[[R0]], r{{[0-9]+}}, r[[R0]]; +;CHECK-NEXT: ld.global.f32 r{{[0-9]+}}, [r[[R0]]]; %i = getelementptr float* %p, i32 %q %x = load float* %i ret float %x @@ -188,9 +188,9 @@ entry: define ptx_device double @t3_f64(double* %p, i32 %q) { entry: -;CHECK: shl.b32 r0, r2, 3; -;CHECK-NEXT: add.u32 r0, r1, r0; -;CHECK-NEXT: ld.global.f64 rd0, [r0]; +;CHECK: shl.b32 r[[R0:[0-9]+]], r{{[0-9]+}}, 3; +;CHECK-NEXT: add.u32 r[[R0]], r{{[0-9]+}}, r[[R0]]; +;CHECK-NEXT: ld.global.f64 rd{{[0-9]+}}, [r[[R0]]]; %i = getelementptr double* %p, i32 %q %x = load double* %i ret double %x @@ -198,8 +198,8 @@ entry: define ptx_device i16 @t4_global_u16() { entry: -;CHECK: mov.u32 r0, array_i16; -;CHECK-NEXT: ld.global.u16 rh0, [r0]; +;CHECK: mov.u32 r[[R0:[0-9]+]], array_i16; +;CHECK-NEXT: ld.global.u16 rh{{[0-9]+}}, [r[[R0]]]; ;CHECK-NEXT: ret; %i = getelementptr [10 x i16]* @array_i16, i32 0, i32 0 %x = load i16* %i @@ -208,8 +208,8 @@ entry: define ptx_device i32 @t4_global_u32() { entry: -;CHECK: mov.u32 r0, array_i32; -;CHECK-NEXT: ld.global.u32 r0, [r0]; +;CHECK: mov.u32 r[[R0:[0-9]+]], array_i32; +;CHECK-NEXT: ld.global.u32 r{{[0-9]+}}, [r[[R0]]]; ;CHECK-NEXT: ret; %i = getelementptr [10 x i32]* @array_i32, i32 0, i32 0 %x = load i32* %i @@ -218,8 +218,8 @@ entry: define ptx_device i64 @t4_global_u64() { entry: -;CHECK: mov.u32 r0, array_i64; -;CHECK-NEXT: ld.global.u64 rd0, [r0]; +;CHECK: mov.u32 r[[R0:[0-9]+]], array_i64; +;CHECK-NEXT: ld.global.u64 rd{{[0-9]+}}, [r[[R0]]]; ;CHECK-NEXT: ret; %i = getelementptr [10 x i64]* @array_i64, i32 0, i32 0 %x = load i64* %i @@ -228,8 +228,8 @@ entry: define ptx_device float @t4_global_f32() { entry: -;CHECK: mov.u32 r0, array_float; -;CHECK-NEXT: ld.global.f32 r0, [r0]; +;CHECK: mov.u32 r[[R0:[0-9]+]], array_float; +;CHECK-NEXT: ld.global.f32 r{{[0-9]+}}, [r[[R0]]]; ;CHECK-NEXT: ret; %i = getelementptr [10 x float]* @array_float, i32 0, i32 0 %x = load float* %i @@ -238,8 +238,8 @@ entry: define ptx_device double @t4_global_f64() { entry: -;CHECK: mov.u32 r0, array_double; -;CHECK-NEXT: ld.global.f64 rd0, [r0]; +;CHECK: mov.u32 r[[R0:[0-9]+]], array_double; +;CHECK-NEXT: ld.global.f64 rd{{[0-9]+}}, [r[[R0]]]; ;CHECK-NEXT: ret; %i = getelementptr [10 x double]* @array_double, i32 0, i32 0 %x = load double* %i @@ -248,8 +248,8 @@ entry: define ptx_device i16 @t4_const_u16() { entry: -;CHECK: mov.u32 r0, array_constant_i16; -;CHECK-NEXT: ld.const.u16 rh0, [r0]; +;CHECK: mov.u32 r[[R0:[0-9]+]], array_constant_i16; +;CHECK-NEXT: ld.const.u16 rh{{[0-9]+}}, [r[[R0]]]; ;CHECK-NEXT: ret; %i = getelementptr [10 x i16] addrspace(1)* @array_constant_i16, i32 0, i32 0 %x = load i16 addrspace(1)* %i @@ -258,8 +258,8 @@ entry: define ptx_device i32 @t4_const_u32() { entry: -;CHECK: mov.u32 r0, array_constant_i32; -;CHECK-NEXT: ld.const.u32 r0, [r0]; +;CHECK: mov.u32 r[[R0:[0-9]+]], array_constant_i32; +;CHECK-NEXT: ld.const.u32 r{{[0-9]+}}, [r[[R0]]]; ;CHECK-NEXT: ret; %i = getelementptr [10 x i32] addrspace(1)* @array_constant_i32, i32 0, i32 0 %x = load i32 addrspace(1)* %i @@ -268,8 +268,8 @@ entry: define ptx_device i64 @t4_const_u64() { entry: -;CHECK: mov.u32 r0, array_constant_i64; -;CHECK-NEXT: ld.const.u64 rd0, [r0]; +;CHECK: mov.u32 r[[R0:[0-9]+]], array_constant_i64; +;CHECK-NEXT: ld.const.u64 rd{{[0-9]+}}, [r[[R0]]]; ;CHECK-NEXT: ret; %i = getelementptr [10 x i64] addrspace(1)* @array_constant_i64, i32 0, i32 0 %x = load i64 addrspace(1)* %i @@ -278,8 +278,8 @@ entry: define ptx_device float @t4_const_f32() { entry: -;CHECK: mov.u32 r0, array_constant_float; -;CHECK-NEXT: ld.const.f32 r0, [r0]; +;CHECK: mov.u32 r[[R0:[0-9]+]], array_constant_float; +;CHECK-NEXT: ld.const.f32 r{{[0-9]+}}, [r[[R0]]]; ;CHECK-NEXT: ret; %i = getelementptr [10 x float] addrspace(1)* @array_constant_float, i32 0, i32 0 %x = load float addrspace(1)* %i @@ -288,8 +288,8 @@ entry: define ptx_device double @t4_const_f64() { entry: -;CHECK: mov.u32 r0, array_constant_double; -;CHECK-NEXT: ld.const.f64 rd0, [r0]; +;CHECK: mov.u32 r[[R0:[0-9]+]], array_constant_double; +;CHECK-NEXT: ld.const.f64 rd{{[0-9]+}}, [r[[R0]]]; ;CHECK-NEXT: ret; %i = getelementptr [10 x double] addrspace(1)* @array_constant_double, i32 0, i32 0 %x = load double addrspace(1)* %i @@ -298,8 +298,8 @@ entry: define ptx_device i16 @t4_local_u16() { entry: -;CHECK: mov.u32 r0, array_local_i16; -;CHECK-NEXT: ld.local.u16 rh0, [r0]; +;CHECK: mov.u32 r[[R0:[0-9]+]], array_local_i16; +;CHECK-NEXT: ld.local.u16 rh{{[0-9]+}}, [r[[R0]]]; ;CHECK-NEXT: ret; %i = getelementptr [10 x i16] addrspace(2)* @array_local_i16, i32 0, i32 0 %x = load i16 addrspace(2)* %i @@ -308,8 +308,8 @@ entry: define ptx_device i32 @t4_local_u32() { entry: -;CHECK: mov.u32 r0, array_local_i32; -;CHECK-NEXT: ld.local.u32 r0, [r0]; +;CHECK: mov.u32 r[[R0:[0-9]+]], array_local_i32; +;CHECK-NEXT: ld.local.u32 r{{[0-9]+}}, [r[[R0]]]; ;CHECK-NEXT: ret; %i = getelementptr [10 x i32] addrspace(2)* @array_local_i32, i32 0, i32 0 %x = load i32 addrspace(2)* %i @@ -318,8 +318,8 @@ entry: define ptx_device i64 @t4_local_u64() { entry: -;CHECK: mov.u32 r0, array_local_i64; -;CHECK-NEXT: ld.local.u64 rd0, [r0]; +;CHECK: mov.u32 r[[R0:[0-9]+]], array_local_i64; +;CHECK-NEXT: ld.local.u64 rd{{[0-9]+}}, [r[[R0]]]; ;CHECK-NEXT: ret; %i = getelementptr [10 x i64] addrspace(2)* @array_local_i64, i32 0, i32 0 %x = load i64 addrspace(2)* %i @@ -328,8 +328,8 @@ entry: define ptx_device float @t4_local_f32() { entry: -;CHECK: mov.u32 r0, array_local_float; -;CHECK-NEXT: ld.local.f32 r0, [r0]; +;CHECK: mov.u32 r[[R0:[0-9]+]], array_local_float; +;CHECK-NEXT: ld.local.f32 r{{[0-9]+}}, [r[[R0]]]; ;CHECK-NEXT: ret; %i = getelementptr [10 x float] addrspace(2)* @array_local_float, i32 0, i32 0 %x = load float addrspace(2)* %i @@ -338,8 +338,8 @@ entry: define ptx_device double @t4_local_f64() { entry: -;CHECK: mov.u32 r0, array_local_double; -;CHECK-NEXT: ld.local.f64 rd0, [r0]; +;CHECK: mov.u32 r[[R0:[0-9]+]], array_local_double; +;CHECK-NEXT: ld.local.f64 rd{{[0-9]+}}, [r[[R0]]]; ;CHECK-NEXT: ret; %i = getelementptr [10 x double] addrspace(2)* @array_local_double, i32 0, i32 0 %x = load double addrspace(2)* %i @@ -348,8 +348,8 @@ entry: define ptx_device i16 @t4_shared_u16() { entry: -;CHECK: mov.u32 r0, array_shared_i16; -;CHECK-NEXT: ld.shared.u16 rh0, [r0]; +;CHECK: mov.u32 r[[R0:[0-9]+]], array_shared_i16; +;CHECK-NEXT: ld.shared.u16 rh{{[0-9]+}}, [r[[R0]]]; ;CHECK-NEXT: ret; %i = getelementptr [10 x i16] addrspace(4)* @array_shared_i16, i32 0, i32 0 %x = load i16 addrspace(4)* %i @@ -358,8 +358,8 @@ entry: define ptx_device i32 @t4_shared_u32() { entry: -;CHECK: mov.u32 r0, array_shared_i32; -;CHECK-NEXT: ld.shared.u32 r0, [r0]; +;CHECK: mov.u32 r[[R0:[0-9]+]], array_shared_i32; +;CHECK-NEXT: ld.shared.u32 r{{[0-9]+}}, [r[[R0]]]; ;CHECK-NEXT: ret; %i = getelementptr [10 x i32] addrspace(4)* @array_shared_i32, i32 0, i32 0 %x = load i32 addrspace(4)* %i @@ -368,8 +368,8 @@ entry: define ptx_device i64 @t4_shared_u64() { entry: -;CHECK: mov.u32 r0, array_shared_i64; -;CHECK-NEXT: ld.shared.u64 rd0, [r0]; +;CHECK: mov.u32 r[[R0:[0-9]+]], array_shared_i64; +;CHECK-NEXT: ld.shared.u64 rd{{[0-9]+}}, [r[[R0]]]; ;CHECK-NEXT: ret; %i = getelementptr [10 x i64] addrspace(4)* @array_shared_i64, i32 0, i32 0 %x = load i64 addrspace(4)* %i @@ -378,8 +378,8 @@ entry: define ptx_device float @t4_shared_f32() { entry: -;CHECK: mov.u32 r0, array_shared_float; -;CHECK-NEXT: ld.shared.f32 r0, [r0]; +;CHECK: mov.u32 r[[R0:[0-9]+]], array_shared_float; +;CHECK-NEXT: ld.shared.f32 r{{[0-9]+}}, [r[[R0]]]; ;CHECK-NEXT: ret; %i = getelementptr [10 x float] addrspace(4)* @array_shared_float, i32 0, i32 0 %x = load float addrspace(4)* %i @@ -388,8 +388,8 @@ entry: define ptx_device double @t4_shared_f64() { entry: -;CHECK: mov.u32 r0, array_shared_double; -;CHECK-NEXT: ld.shared.f64 rd0, [r0]; +;CHECK: mov.u32 r[[R0:[0-9]+]], array_shared_double; +;CHECK-NEXT: ld.shared.f64 rd{{[0-9]+}}, [r[[R0]]]; ;CHECK-NEXT: ret; %i = getelementptr [10 x double] addrspace(4)* @array_shared_double, i32 0, i32 0 %x = load double addrspace(4)* %i @@ -398,8 +398,8 @@ entry: define ptx_device i16 @t5_u16() { entry: -;CHECK: mov.u32 r0, array_i16; -;CHECK-NEXT: ld.global.u16 rh0, [r0+2]; +;CHECK: mov.u32 r[[R0:[0-9]+]], array_i16; +;CHECK-NEXT: ld.global.u16 rh{{[0-9]+}}, [r[[R0]]+2]; ;CHECK-NEXT: ret; %i = getelementptr [10 x i16]* @array_i16, i32 0, i32 1 %x = load i16* %i @@ -408,8 +408,8 @@ entry: define ptx_device i32 @t5_u32() { entry: -;CHECK: mov.u32 r0, array_i32; -;CHECK-NEXT: ld.global.u32 r0, [r0+4]; +;CHECK: mov.u32 r[[R0:[0-9]+]], array_i32; +;CHECK-NEXT: ld.global.u32 r{{[0-9]+}}, [r[[R0]]+4]; ;CHECK-NEXT: ret; %i = getelementptr [10 x i32]* @array_i32, i32 0, i32 1 %x = load i32* %i @@ -418,8 +418,8 @@ entry: define ptx_device i64 @t5_u64() { entry: -;CHECK: mov.u32 r0, array_i64; -;CHECK-NEXT: ld.global.u64 rd0, [r0+8]; +;CHECK: mov.u32 r[[R0:[0-9]+]], array_i64; +;CHECK-NEXT: ld.global.u64 rd{{[0-9]+}}, [r[[R0]]+8]; ;CHECK-NEXT: ret; %i = getelementptr [10 x i64]* @array_i64, i32 0, i32 1 %x = load i64* %i @@ -428,8 +428,8 @@ entry: define ptx_device float @t5_f32() { entry: -;CHECK: mov.u32 r0, array_float; -;CHECK-NEXT: ld.global.f32 r0, [r0+4]; +;CHECK: mov.u32 r[[R0:[0-9]+]], array_float; +;CHECK-NEXT: ld.global.f32 r{{[0-9]+}}, [r[[R0]]+4]; ;CHECK-NEXT: ret; %i = getelementptr [10 x float]* @array_float, i32 0, i32 1 %x = load float* %i @@ -438,8 +438,8 @@ entry: define ptx_device double @t5_f64() { entry: -;CHECK: mov.u32 r0, array_double; -;CHECK-NEXT: ld.global.f64 rd0, [r0+8]; +;CHECK: mov.u32 r[[R0:[0-9]+]], array_double; +;CHECK-NEXT: ld.global.f64 rd{{[0-9]+}}, [r[[R0]]+8]; ;CHECK-NEXT: ret; %i = getelementptr [10 x double]* @array_double, i32 0, i32 1 %x = load double* %i diff --git a/test/CodeGen/PTX/llvm-intrinsic.ll b/test/CodeGen/PTX/llvm-intrinsic.ll index 9c532c1..4611c54 100644 --- a/test/CodeGen/PTX/llvm-intrinsic.ll +++ b/test/CodeGen/PTX/llvm-intrinsic.ll @@ -2,7 +2,7 @@ define ptx_device float @test_sqrt_f32(float %x) { entry: -; CHECK: sqrt.rn.f32 r0, r1; +; CHECK: sqrt.rn.f32 r{{[0-9]+}}, r{{[0-9]+}}; ; CHECK-NEXT: ret; %y = call float @llvm.sqrt.f32(float %x) ret float %y @@ -10,7 +10,7 @@ entry: define ptx_device double @test_sqrt_f64(double %x) { entry: -; CHECK: sqrt.rn.f64 rd0, rd1; +; CHECK: sqrt.rn.f64 rd{{[0-9]+}}, rd{{[0-9]+}}; ; CHECK-NEXT: ret; %y = call double @llvm.sqrt.f64(double %x) ret double %y @@ -18,7 +18,7 @@ entry: define ptx_device float @test_sin_f32(float %x) { entry: -; CHECK: sin.approx.f32 r0, r1; +; CHECK: sin.approx.f32 r{{[0-9]+}}, r{{[0-9]+}}; ; CHECK-NEXT: ret; %y = call float @llvm.sin.f32(float %x) ret float %y @@ -26,7 +26,7 @@ entry: define ptx_device double @test_sin_f64(double %x) { entry: -; CHECK: sin.approx.f64 rd0, rd1; +; CHECK: sin.approx.f64 rd{{[0-9]+}}, rd{{[0-9]+}}; ; CHECK-NEXT: ret; %y = call double @llvm.sin.f64(double %x) ret double %y @@ -34,7 +34,7 @@ entry: define ptx_device float @test_cos_f32(float %x) { entry: -; CHECK: cos.approx.f32 r0, r1; +; CHECK: cos.approx.f32 r{{[0-9]+}}, r{{[0-9]+}}; ; CHECK-NEXT: ret; %y = call float @llvm.cos.f32(float %x) ret float %y @@ -42,7 +42,7 @@ entry: define ptx_device double @test_cos_f64(double %x) { entry: -; CHECK: cos.approx.f64 rd0, rd1; +; CHECK: cos.approx.f64 rd{{[0-9]+}}, rd{{[0-9]+}}; ; CHECK-NEXT: ret; %y = call double @llvm.cos.f64(double %x) ret double %y diff --git a/test/CodeGen/PTX/mad.ll b/test/CodeGen/PTX/mad.ll index 56d3811..0e4d3f9 100644 --- a/test/CodeGen/PTX/mad.ll +++ b/test/CodeGen/PTX/mad.ll @@ -1,7 +1,7 @@ ; RUN: llc < %s -march=ptx32 -mattr=+sm13 | FileCheck %s define ptx_device float @t1_f32(float %x, float %y, float %z) { -; CHECK: mad.rn.f32 r0, r1, r2, r3; +; CHECK: mad.rn.f32 r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}; ; CHECK-NEXT: ret; %a = fmul float %x, %y %b = fadd float %a, %z @@ -9,7 +9,7 @@ define ptx_device float @t1_f32(float %x, float %y, float %z) { } define ptx_device double @t1_f64(double %x, double %y, double %z) { -; CHECK: mad.rn.f64 rd0, rd1, rd2, rd3; +; CHECK: mad.rn.f64 rd{{[0-9]+}}, rd{{[0-9]+}}, rd{{[0-9]+}}, rd{{[0-9]+}}; ; CHECK-NEXT: ret; %a = fmul double %x, %y %b = fadd double %a, %z diff --git a/test/CodeGen/PTX/mov.ll b/test/CodeGen/PTX/mov.ll index 05ce4c0..cce6a5b 100644 --- a/test/CodeGen/PTX/mov.ll +++ b/test/CodeGen/PTX/mov.ll @@ -1,61 +1,61 @@ ; RUN: llc < %s -march=ptx32 | FileCheck %s define ptx_device i16 @t1_u16() { -; CHECK: mov.u16 rh0, 0; +; CHECK: mov.u16 rh{{[0-9]+}}, 0; ; CHECK: ret; ret i16 0 } define ptx_device i32 @t1_u32() { -; CHECK: mov.u32 r0, 0; +; CHECK: mov.u32 r{{[0-9]+}}, 0; ; CHECK: ret; ret i32 0 } define ptx_device i64 @t1_u64() { -; CHECK: mov.u64 rd0, 0; +; CHECK: mov.u64 rd{{[0-9]+}}, 0; ; CHECK: ret; ret i64 0 } define ptx_device float @t1_f32() { -; CHECK: mov.f32 r0, 0F00000000; +; CHECK: mov.f32 r{{[0-9]+}}, 0F00000000; ; CHECK: ret; ret float 0.0 } define ptx_device double @t1_f64() { -; CHECK: mov.f64 rd0, 0D0000000000000000; +; CHECK: mov.f64 rd{{[0-9]+}}, 0D0000000000000000; ; CHECK: ret; ret double 0.0 } define ptx_device i16 @t2_u16(i16 %x) { -; CHECK: mov.u16 rh0, rh1; +; CHECK: mov.u16 rh{{[0-9]+}}, rh{{[0-9]+}}; ; CHECK: ret; ret i16 %x } define ptx_device i32 @t2_u32(i32 %x) { -; CHECK: mov.u32 r0, r1; +; CHECK: mov.u32 r{{[0-9]+}}, r{{[0-9]+}}; ; CHECK: ret; ret i32 %x } define ptx_device i64 @t2_u64(i64 %x) { -; CHECK: mov.u64 rd0, rd1; +; CHECK: mov.u64 rd{{[0-9]+}}, rd{{[0-9]+}}; ; CHECK: ret; ret i64 %x } define ptx_device float @t3_f32(float %x) { -; CHECK: mov.u32 r0, r1; +; CHECK: mov.u32 r{{[0-9]+}}, r{{[0-9]+}}; ; CHECK-NEXT: ret; ret float %x } define ptx_device double @t3_f64(double %x) { -; CHECK: mov.u64 rd0, rd1; +; CHECK: mov.u64 rd{{[0-9]+}}, rd{{[0-9]+}}; ; CHECK-NEXT: ret; ret double %x } diff --git a/test/CodeGen/PTX/mul.ll b/test/CodeGen/PTX/mul.ll index 2093556..491cc74 100644 --- a/test/CodeGen/PTX/mul.ll +++ b/test/CodeGen/PTX/mul.ll @@ -11,28 +11,28 @@ ;} define ptx_device float @t1_f32(float %x, float %y) { -; CHECK: mul.rn.f32 r0, r1, r2 +; CHECK: mul.rn.f32 r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}} ; CHECK-NEXT: ret; %z = fmul float %x, %y ret float %z } define ptx_device double @t1_f64(double %x, double %y) { -; CHECK: mul.rn.f64 rd0, rd1, rd2 +; CHECK: mul.rn.f64 rd{{[0-9]+}}, rd{{[0-9]+}}, rd{{[0-9]+}} ; CHECK-NEXT: ret; %z = fmul double %x, %y ret double %z } define ptx_device float @t2_f32(float %x) { -; CHECK: mul.rn.f32 r0, r1, 0F40A00000; +; CHECK: mul.rn.f32 r{{[0-9]+}}, r{{[0-9]+}}, 0F40A00000; ; CHECK-NEXT: ret; %z = fmul float %x, 5.0 ret float %z } define ptx_device double @t2_f64(double %x) { -; CHECK: mul.rn.f64 rd0, rd1, 0D4014000000000000; +; CHECK: mul.rn.f64 rd{{[0-9]+}}, rd{{[0-9]+}}, 0D4014000000000000; ; CHECK-NEXT: ret; %z = fmul double %x, 5.0 ret double %z diff --git a/test/CodeGen/PTX/parameter-order.ll b/test/CodeGen/PTX/parameter-order.ll index 5486472..b16556e 100644 --- a/test/CodeGen/PTX/parameter-order.ll +++ b/test/CodeGen/PTX/parameter-order.ll @@ -1,8 +1,8 @@ ; RUN: llc < %s -march=ptx32 | FileCheck %s -; CHECK: .func (.reg .b32 r0) test_parameter_order (.reg .b32 r1, .reg .b32 r2, .reg .b32 r3, .reg .b32 r4) +; CHECK: .func (.reg .b32 r{{[0-9]+}}) test_parameter_order (.reg .b32 r{{[0-9]+}}, .reg .b32 r{{[0-9]+}}, .reg .b32 r{{[0-9]+}}, .reg .b32 r{{[0-9]+}}) define ptx_device i32 @test_parameter_order(float %a, i32 %b, i32 %c, float %d) { -; CHECK: sub.u32 r0, r2, r3 +; CHECK: sub.u32 r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}} %result = sub i32 %b, %c ret i32 %result } diff --git a/test/CodeGen/PTX/selp.ll b/test/CodeGen/PTX/selp.ll index 19cfa53..e705fbe 100644 --- a/test/CodeGen/PTX/selp.ll +++ b/test/CodeGen/PTX/selp.ll @@ -1,25 +1,25 @@ ; RUN: llc < %s -march=ptx32 | FileCheck %s define ptx_device i32 @test_selp_i32(i1 %x, i32 %y, i32 %z) { -; CHECK: selp.u32 r0, r1, r2, p1; +; CHECK: selp.u32 r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, p{{[0-9]+}}; %a = select i1 %x, i32 %y, i32 %z ret i32 %a } define ptx_device i64 @test_selp_i64(i1 %x, i64 %y, i64 %z) { -; CHECK: selp.u64 rd0, rd1, rd2, p1; +; CHECK: selp.u64 rd{{[0-9]+}}, rd{{[0-9]+}}, rd{{[0-9]+}}, p{{[0-9]+}}; %a = select i1 %x, i64 %y, i64 %z ret i64 %a } define ptx_device float @test_selp_f32(i1 %x, float %y, float %z) { -; CHECK: selp.f32 r0, r1, r2, p1; +; CHECK: selp.f32 r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, p{{[0-9]+}}; %a = select i1 %x, float %y, float %z ret float %a } define ptx_device double @test_selp_f64(i1 %x, double %y, double %z) { -; CHECK: selp.f64 rd0, rd1, rd2, p1; +; CHECK: selp.f64 rd{{[0-9]+}}, rd{{[0-9]+}}, rd{{[0-9]+}}, p{{[0-9]+}}; %a = select i1 %x, double %y, double %z ret double %a } diff --git a/test/CodeGen/PTX/setp.ll b/test/CodeGen/PTX/setp.ll index 3e01a75..b8cb364 100644 --- a/test/CodeGen/PTX/setp.ll +++ b/test/CodeGen/PTX/setp.ll @@ -1,8 +1,8 @@ ; RUN: llc < %s -march=ptx32 | FileCheck %s define ptx_device i32 @test_setp_eq_u32_rr(i32 %x, i32 %y) { -; CHECK: setp.eq.u32 p0, r1, r2; -; CHECK-NEXT: selp.u32 r0, 1, 0, p0; +; CHECK: setp.eq.u32 p[[P0:[0-9]+]], r{{[0-9]+}}, r{{[0-9]+}}; +; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0]]; ; CHECK-NEXT: ret; %p = icmp eq i32 %x, %y %z = zext i1 %p to i32 @@ -10,8 +10,8 @@ define ptx_device i32 @test_setp_eq_u32_rr(i32 %x, i32 %y) { } define ptx_device i32 @test_setp_ne_u32_rr(i32 %x, i32 %y) { -; CHECK: setp.ne.u32 p0, r1, r2; -; CHECK-NEXT: selp.u32 r0, 1, 0, p0; +; CHECK: setp.ne.u32 p[[P0:[0-9]+]], r{{[0-9]+}}, r{{[0-9]+}}; +; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0]]; ; CHECK-NEXT: ret; %p = icmp ne i32 %x, %y %z = zext i1 %p to i32 @@ -19,8 +19,8 @@ define ptx_device i32 @test_setp_ne_u32_rr(i32 %x, i32 %y) { } define ptx_device i32 @test_setp_lt_u32_rr(i32 %x, i32 %y) { -; CHECK: setp.lt.u32 p0, r1, r2; -; CHECK-NEXT: selp.u32 r0, 1, 0, p0; +; CHECK: setp.lt.u32 p[[P0:[0-9]+]], r{{[0-9]+}}, r{{[0-9]+}}; +; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0]]; ; CHECK-NEXT: ret; %p = icmp ult i32 %x, %y %z = zext i1 %p to i32 @@ -28,8 +28,8 @@ define ptx_device i32 @test_setp_lt_u32_rr(i32 %x, i32 %y) { } define ptx_device i32 @test_setp_le_u32_rr(i32 %x, i32 %y) { -; CHECK: setp.le.u32 p0, r1, r2; -; CHECK-NEXT: selp.u32 r0, 1, 0, p0; +; CHECK: setp.le.u32 p[[P0:[0-9]+]], r{{[0-9]+}}, r{{[0-9]+}}; +; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0]]; ; CHECK-NEXT: ret; %p = icmp ule i32 %x, %y %z = zext i1 %p to i32 @@ -37,8 +37,8 @@ define ptx_device i32 @test_setp_le_u32_rr(i32 %x, i32 %y) { } define ptx_device i32 @test_setp_gt_u32_rr(i32 %x, i32 %y) { -; CHECK: setp.gt.u32 p0, r1, r2; -; CHECK-NEXT: selp.u32 r0, 1, 0, p0; +; CHECK: setp.gt.u32 p[[P0:[0-9]+]], r{{[0-9]+}}, r{{[0-9]+}}; +; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0]]; ; CHECK-NEXT: ret; %p = icmp ugt i32 %x, %y %z = zext i1 %p to i32 @@ -46,8 +46,8 @@ define ptx_device i32 @test_setp_gt_u32_rr(i32 %x, i32 %y) { } define ptx_device i32 @test_setp_ge_u32_rr(i32 %x, i32 %y) { -; CHECK: setp.ge.u32 p0, r1, r2; -; CHECK-NEXT: selp.u32 r0, 1, 0, p0; +; CHECK: setp.ge.u32 p[[P0:[0-9]+]], r{{[0-9]+}}, r{{[0-9]+}}; +; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0]]; ; CHECK-NEXT: ret; %p = icmp uge i32 %x, %y %z = zext i1 %p to i32 @@ -55,8 +55,8 @@ define ptx_device i32 @test_setp_ge_u32_rr(i32 %x, i32 %y) { } define ptx_device i32 @test_setp_lt_s32_rr(i32 %x, i32 %y) { -; CHECK: setp.lt.s32 p0, r1, r2; -; CHECK-NEXT: selp.u32 r0, 1, 0, p0; +; CHECK: setp.lt.s32 p[[P0:[0-9]+]], r{{[0-9]+}}, r{{[0-9]+}}; +; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0]]; ; CHECK-NEXT: ret; %p = icmp slt i32 %x, %y %z = zext i1 %p to i32 @@ -64,8 +64,8 @@ define ptx_device i32 @test_setp_lt_s32_rr(i32 %x, i32 %y) { } define ptx_device i32 @test_setp_le_s32_rr(i32 %x, i32 %y) { -; CHECK: setp.le.s32 p0, r1, r2; -; CHECK-NEXT: selp.u32 r0, 1, 0, p0; +; CHECK: setp.le.s32 p[[P0:[0-9]+]], r{{[0-9]+}}, r{{[0-9]+}}; +; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0]]; ; CHECK-NEXT: ret; %p = icmp sle i32 %x, %y %z = zext i1 %p to i32 @@ -73,8 +73,8 @@ define ptx_device i32 @test_setp_le_s32_rr(i32 %x, i32 %y) { } define ptx_device i32 @test_setp_gt_s32_rr(i32 %x, i32 %y) { -; CHECK: setp.gt.s32 p0, r1, r2; -; CHECK-NEXT: selp.u32 r0, 1, 0, p0; +; CHECK: setp.gt.s32 p[[P0:[0-9]+]], r{{[0-9]+}}, r{{[0-9]+}}; +; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0]]; ; CHECK-NEXT: ret; %p = icmp sgt i32 %x, %y %z = zext i1 %p to i32 @@ -82,8 +82,8 @@ define ptx_device i32 @test_setp_gt_s32_rr(i32 %x, i32 %y) { } define ptx_device i32 @test_setp_ge_s32_rr(i32 %x, i32 %y) { -; CHECK: setp.ge.s32 p0, r1, r2; -; CHECK-NEXT: selp.u32 r0, 1, 0, p0; +; CHECK: setp.ge.s32 p[[P0:[0-9]+]], r{{[0-9]+}}, r{{[0-9]+}}; +; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0]]; ; CHECK-NEXT: ret; %p = icmp sge i32 %x, %y %z = zext i1 %p to i32 @@ -91,8 +91,8 @@ define ptx_device i32 @test_setp_ge_s32_rr(i32 %x, i32 %y) { } define ptx_device i32 @test_setp_eq_u32_ri(i32 %x) { -; CHECK: setp.eq.u32 p0, r1, 1; -; CHECK-NEXT: selp.u32 r0, 1, 0, p0; +; CHECK: setp.eq.u32 p[[P0:[0-9]+]], r{{[0-9]+}}, 1; +; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0]]; ; CHECK-NEXT: ret; %p = icmp eq i32 %x, 1 %z = zext i1 %p to i32 @@ -100,8 +100,8 @@ define ptx_device i32 @test_setp_eq_u32_ri(i32 %x) { } define ptx_device i32 @test_setp_ne_u32_ri(i32 %x) { -; CHECK: setp.ne.u32 p0, r1, 1; -; CHECK-NEXT: selp.u32 r0, 1, 0, p0; +; CHECK: setp.ne.u32 p[[P0:[0-9]+]], r{{[0-9]+}}, 1; +; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0]]; ; CHECK-NEXT: ret; %p = icmp ne i32 %x, 1 %z = zext i1 %p to i32 @@ -109,8 +109,8 @@ define ptx_device i32 @test_setp_ne_u32_ri(i32 %x) { } define ptx_device i32 @test_setp_lt_u32_ri(i32 %x) { -; CHECK: setp.eq.u32 p0, r1, 0; -; CHECK-NEXT: selp.u32 r0, 1, 0, p0; +; CHECK: setp.eq.u32 p[[P0:[0-9]+]], r{{[0-9]+}}, 0; +; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0]]; ; CHECK-NEXT: ret; %p = icmp ult i32 %x, 1 %z = zext i1 %p to i32 @@ -118,8 +118,8 @@ define ptx_device i32 @test_setp_lt_u32_ri(i32 %x) { } define ptx_device i32 @test_setp_le_u32_ri(i32 %x) { -; CHECK: setp.lt.u32 p0, r1, 2; -; CHECK-NEXT: selp.u32 r0, 1, 0, p0; +; CHECK: setp.lt.u32 p[[P0:[0-9]+]], r{{[0-9]+}}, 2; +; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0]]; ; CHECK-NEXT: ret; %p = icmp ule i32 %x, 1 %z = zext i1 %p to i32 @@ -127,8 +127,8 @@ define ptx_device i32 @test_setp_le_u32_ri(i32 %x) { } define ptx_device i32 @test_setp_gt_u32_ri(i32 %x) { -; CHECK: setp.gt.u32 p0, r1, 1; -; CHECK-NEXT: selp.u32 r0, 1, 0, p0; +; CHECK: setp.gt.u32 p[[P0:[0-9]+]], r{{[0-9]+}}, 1; +; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0]]; ; CHECK-NEXT: ret; %p = icmp ugt i32 %x, 1 %z = zext i1 %p to i32 @@ -136,8 +136,8 @@ define ptx_device i32 @test_setp_gt_u32_ri(i32 %x) { } define ptx_device i32 @test_setp_ge_u32_ri(i32 %x) { -; CHECK: setp.ne.u32 p0, r1, 0; -; CHECK-NEXT: selp.u32 r0, 1, 0, p0; +; CHECK: setp.ne.u32 p[[P0:[0-9]+]], r{{[0-9]+}}, 0; +; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0]]; ; CHECK-NEXT: ret; %p = icmp uge i32 %x, 1 %z = zext i1 %p to i32 @@ -145,8 +145,8 @@ define ptx_device i32 @test_setp_ge_u32_ri(i32 %x) { } define ptx_device i32 @test_setp_lt_s32_ri(i32 %x) { -; CHECK: setp.lt.s32 p0, r1, 1; -; CHECK-NEXT: selp.u32 r0, 1, 0, p0; +; CHECK: setp.lt.s32 p[[P0:[0-9]+]], r{{[0-9]+}}, 1; +; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0]]; ; CHECK-NEXT: ret; %p = icmp slt i32 %x, 1 %z = zext i1 %p to i32 @@ -154,8 +154,8 @@ define ptx_device i32 @test_setp_lt_s32_ri(i32 %x) { } define ptx_device i32 @test_setp_le_s32_ri(i32 %x) { -; CHECK: setp.lt.s32 p0, r1, 2; -; CHECK-NEXT: selp.u32 r0, 1, 0, p0; +; CHECK: setp.lt.s32 p[[P0:[0-9]+]], r{{[0-9]+}}, 2; +; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0]]; ; CHECK-NEXT: ret; %p = icmp sle i32 %x, 1 %z = zext i1 %p to i32 @@ -163,8 +163,8 @@ define ptx_device i32 @test_setp_le_s32_ri(i32 %x) { } define ptx_device i32 @test_setp_gt_s32_ri(i32 %x) { -; CHECK: setp.gt.s32 p0, r1, 1; -; CHECK-NEXT: selp.u32 r0, 1, 0, p0; +; CHECK: setp.gt.s32 p[[P0:[0-9]+]], r{{[0-9]+}}, 1; +; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0]]; ; CHECK-NEXT: ret; %p = icmp sgt i32 %x, 1 %z = zext i1 %p to i32 @@ -172,8 +172,8 @@ define ptx_device i32 @test_setp_gt_s32_ri(i32 %x) { } define ptx_device i32 @test_setp_ge_s32_ri(i32 %x) { -; CHECK: setp.gt.s32 p0, r1, 0; -; CHECK-NEXT: selp.u32 r0, 1, 0, p0; +; CHECK: setp.gt.s32 p[[P0:[0-9]+]], r{{[0-9]+}}, 0; +; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0]]; ; CHECK-NEXT: ret; %p = icmp sge i32 %x, 1 %z = zext i1 %p to i32 @@ -181,9 +181,9 @@ define ptx_device i32 @test_setp_ge_s32_ri(i32 %x) { } define ptx_device i32 @test_setp_4_op_format_1(i32 %x, i32 %y, i32 %u, i32 %v) { -; CHECK: setp.gt.u32 p0, r3, r4; -; CHECK-NEXT: setp.eq.and.u32 p0, r1, r2, p0; -; CHECK-NEXT: selp.u32 r0, 1, 0, p0; +; CHECK: setp.gt.u32 p[[P0:[0-9]+]], r{{[0-9]+}}, r{{[0-9]+}}; +; CHECK-NEXT: setp.eq.and.u32 p[[P0]], r{{[0-9]+}}, r{{[0-9]+}}, p[[P0]]; +; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0]]; ; CHECK-NEXT: ret; %c = icmp eq i32 %x, %y %d = icmp ugt i32 %u, %v @@ -193,9 +193,9 @@ define ptx_device i32 @test_setp_4_op_format_1(i32 %x, i32 %y, i32 %u, i32 %v) { } define ptx_device i32 @test_setp_4_op_format_2(i32 %x, i32 %y, i32 %w) { -; CHECK: setp.gt.b32 p0, r3, 0; -; CHECK-NEXT: setp.eq.and.u32 p0, r1, r2, !p0; -; CHECK-NEXT: selp.u32 r0, 1, 0, p0; +; CHECK: setp.gt.b32 p[[P0:[0-9]+]], r{{[0-9]+}}, 0; +; CHECK-NEXT: setp.eq.and.u32 p[[P0]], r{{[0-9]+}}, r{{[0-9]+}}, !p[[P0]]; +; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0]]; ; CHECK-NEXT: ret; %c = trunc i32 %w to i1 %d = icmp eq i32 %x, %y diff --git a/test/CodeGen/PTX/shl.ll b/test/CodeGen/PTX/shl.ll index 6e72c92..b3818e1 100644 --- a/test/CodeGen/PTX/shl.ll +++ b/test/CodeGen/PTX/shl.ll @@ -1,21 +1,21 @@ ; RUN: llc < %s -march=ptx32 | FileCheck %s define ptx_device i32 @t1(i32 %x, i32 %y) { -; CHECK: shl.b32 r0, r1, r2 +; CHECK: shl.b32 r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}} %z = shl i32 %x, %y ; CHECK: ret; ret i32 %z } define ptx_device i32 @t2(i32 %x) { -; CHECK: shl.b32 r0, r1, 3 +; CHECK: shl.b32 r{{[0-9]+}}, r{{[0-9]+}}, 3 %z = shl i32 %x, 3 ; CHECK: ret; ret i32 %z } define ptx_device i32 @t3(i32 %x) { -; CHECK: shl.b32 r0, 3, r1 +; CHECK: shl.b32 r{{[0-9]+}}, 3, r{{[0-9]+}} %z = shl i32 3, %x ; CHECK: ret; ret i32 %z diff --git a/test/CodeGen/PTX/shr.ll b/test/CodeGen/PTX/shr.ll index 8693e0e..cb57546 100644 --- a/test/CodeGen/PTX/shr.ll +++ b/test/CodeGen/PTX/shr.ll @@ -1,42 +1,42 @@ ; RUN: llc < %s -march=ptx32 | FileCheck %s define ptx_device i32 @t1(i32 %x, i32 %y) { -; CHECK: shr.u32 r0, r1, r2 +; CHECK: shr.u32 r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}} %z = lshr i32 %x, %y ; CHECK: ret; ret i32 %z } define ptx_device i32 @t2(i32 %x) { -; CHECK: shr.u32 r0, r1, 3 +; CHECK: shr.u32 r{{[0-9]+}}, r{{[0-9]+}}, 3 %z = lshr i32 %x, 3 ; CHECK: ret; ret i32 %z } define ptx_device i32 @t3(i32 %x) { -; CHECK: shr.u32 r0, 3, r1 +; CHECK: shr.u32 r{{[0-9]+}}, 3, r{{[0-9]+}} %z = lshr i32 3, %x ; CHECK: ret; ret i32 %z } define ptx_device i32 @t4(i32 %x, i32 %y) { -; CHECK: shr.s32 r0, r1, r2 +; CHECK: shr.s32 r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}} %z = ashr i32 %x, %y ; CHECK: ret; ret i32 %z } define ptx_device i32 @t5(i32 %x) { -; CHECK: shr.s32 r0, r1, 3 +; CHECK: shr.s32 r{{[0-9]+}}, r{{[0-9]+}}, 3 %z = ashr i32 %x, 3 ; CHECK: ret; ret i32 %z } define ptx_device i32 @t6(i32 %x) { -; CHECK: shr.s32 r0, -3, r1 +; CHECK: shr.s32 r{{[0-9]+}}, -3, r{{[0-9]+}} %z = ashr i32 -3, %x ; CHECK: ret; ret i32 %z diff --git a/test/CodeGen/PTX/st.ll b/test/CodeGen/PTX/st.ll index 612967a..b08528e 100644 --- a/test/CodeGen/PTX/st.ll +++ b/test/CodeGen/PTX/st.ll @@ -63,7 +63,7 @@ define ptx_device void @t1_u16(i16* %p, i16 %x) { entry: -;CHECK: st.global.u16 [r1], rh1; +;CHECK: st.global.u16 [r{{[0-9]+}}], rh{{[0-9]+}}; ;CHECK-NEXT: ret; store i16 %x, i16* %p ret void @@ -71,7 +71,7 @@ entry: define ptx_device void @t1_u32(i32* %p, i32 %x) { entry: -;CHECK: st.global.u32 [r1], r2; +;CHECK: st.global.u32 [r{{[0-9]+}}], r{{[0-9]+}}; ;CHECK-NEXT: ret; store i32 %x, i32* %p ret void @@ -79,7 +79,7 @@ entry: define ptx_device void @t1_u64(i64* %p, i64 %x) { entry: -;CHECK: st.global.u64 [r1], rd1; +;CHECK: st.global.u64 [r{{[0-9]+}}], rd{{[0-9]+}}; ;CHECK-NEXT: ret; store i64 %x, i64* %p ret void @@ -87,7 +87,7 @@ entry: define ptx_device void @t1_f32(float* %p, float %x) { entry: -;CHECK: st.global.f32 [r1], r2; +;CHECK: st.global.f32 [r{{[0-9]+}}], r{{[0-9]+}}; ;CHECK-NEXT: ret; store float %x, float* %p ret void @@ -95,7 +95,7 @@ entry: define ptx_device void @t1_f64(double* %p, double %x) { entry: -;CHECK: st.global.f64 [r1], rd1; +;CHECK: st.global.f64 [r{{[0-9]+}}], rd{{[0-9]+}}; ;CHECK-NEXT: ret; store double %x, double* %p ret void @@ -103,7 +103,7 @@ entry: define ptx_device void @t2_u16(i16* %p, i16 %x) { entry: -;CHECK: st.global.u16 [r1+2], rh1; +;CHECK: st.global.u16 [r{{[0-9]+}}+2], rh{{[0-9]+}}; ;CHECK-NEXT: ret; %i = getelementptr i16* %p, i32 1 store i16 %x, i16* %i @@ -112,7 +112,7 @@ entry: define ptx_device void @t2_u32(i32* %p, i32 %x) { entry: -;CHECK: st.global.u32 [r1+4], r2; +;CHECK: st.global.u32 [r{{[0-9]+}}+4], r{{[0-9]+}}; ;CHECK-NEXT: ret; %i = getelementptr i32* %p, i32 1 store i32 %x, i32* %i @@ -121,7 +121,7 @@ entry: define ptx_device void @t2_u64(i64* %p, i64 %x) { entry: -;CHECK: st.global.u64 [r1+8], rd1; +;CHECK: st.global.u64 [r{{[0-9]+}}+8], rd{{[0-9]+}}; ;CHECK-NEXT: ret; %i = getelementptr i64* %p, i32 1 store i64 %x, i64* %i @@ -130,7 +130,7 @@ entry: define ptx_device void @t2_f32(float* %p, float %x) { entry: -;CHECK: st.global.f32 [r1+4], r2; +;CHECK: st.global.f32 [r{{[0-9]+}}+4], r{{[0-9]+}}; ;CHECK-NEXT: ret; %i = getelementptr float* %p, i32 1 store float %x, float* %i @@ -139,7 +139,7 @@ entry: define ptx_device void @t2_f64(double* %p, double %x) { entry: -;CHECK: st.global.f64 [r1+8], rd1; +;CHECK: st.global.f64 [r{{[0-9]+}}+8], rd{{[0-9]+}}; ;CHECK-NEXT: ret; %i = getelementptr double* %p, i32 1 store double %x, double* %i @@ -148,9 +148,9 @@ entry: define ptx_device void @t3_u16(i16* %p, i32 %q, i16 %x) { entry: -;CHECK: shl.b32 r0, r2, 1; -;CHECK-NEXT: add.u32 r0, r1, r0; -;CHECK-NEXT: st.global.u16 [r0], rh1; +;CHECK: shl.b32 r[[R0:[0-9]+]], r{{[0-9]+}}, 1; +;CHECK-NEXT: add.u32 r[[R0]], r{{[0-9]+}}, r[[R0]]; +;CHECK-NEXT: st.global.u16 [r[[R0]]], rh{{[0-9]+}}; ;CHECK-NEXT: ret; %i = getelementptr i16* %p, i32 %q store i16 %x, i16* %i @@ -159,9 +159,9 @@ entry: define ptx_device void @t3_u32(i32* %p, i32 %q, i32 %x) { entry: -;CHECK: shl.b32 r0, r2, 2; -;CHECK-NEXT: add.u32 r0, r1, r0; -;CHECK-NEXT: st.global.u32 [r0], r3; +;CHECK: shl.b32 r[[R0:[0-9]+]], r{{[0-9]+}}, 2; +;CHECK-NEXT: add.u32 r[[R0]], r{{[0-9]+}}, r[[R0]]; +;CHECK-NEXT: st.global.u32 [r[[R0]]], r{{[0-9]+}}; ;CHECK-NEXT: ret; %i = getelementptr i32* %p, i32 %q store i32 %x, i32* %i @@ -170,9 +170,9 @@ entry: define ptx_device void @t3_u64(i64* %p, i32 %q, i64 %x) { entry: -;CHECK: shl.b32 r0, r2, 3; -;CHECK-NEXT: add.u32 r0, r1, r0; -;CHECK-NEXT: st.global.u64 [r0], rd1; +;CHECK: shl.b32 r[[R0:[0-9]+]], r{{[0-9]+}}, 3; +;CHECK-NEXT: add.u32 r[[R0]], r{{[0-9]+}}, r[[R0]]; +;CHECK-NEXT: st.global.u64 [r[[R0]]], rd{{[0-9]+}}; ;CHECK-NEXT: ret; %i = getelementptr i64* %p, i32 %q store i64 %x, i64* %i @@ -181,9 +181,9 @@ entry: define ptx_device void @t3_f32(float* %p, i32 %q, float %x) { entry: -;CHECK: shl.b32 r0, r2, 2; -;CHECK-NEXT: add.u32 r0, r1, r0; -;CHECK-NEXT: st.global.f32 [r0], r3; +;CHECK: shl.b32 r[[R0:[0-9]+]], r{{[0-9]+}}, 2; +;CHECK-NEXT: add.u32 r[[R0]], r{{[0-9]+}}, r[[R0]]; +;CHECK-NEXT: st.global.f32 [r[[R0]]], r{{[0-9]+}}; ;CHECK-NEXT: ret; %i = getelementptr float* %p, i32 %q store float %x, float* %i @@ -192,9 +192,9 @@ entry: define ptx_device void @t3_f64(double* %p, i32 %q, double %x) { entry: -;CHECK: shl.b32 r0, r2, 3; -;CHECK-NEXT: add.u32 r0, r1, r0; -;CHECK-NEXT: st.global.f64 [r0], rd1; +;CHECK: shl.b32 r[[R0:[0-9]+]], r{{[0-9]+}}, 3; +;CHECK-NEXT: add.u32 r[[R0]], r{{[0-9]+}}, r[[R0]]; +;CHECK-NEXT: st.global.f64 [r[[R0]]], rd{{[0-9]+}}; ;CHECK-NEXT: ret; %i = getelementptr double* %p, i32 %q store double %x, double* %i @@ -203,8 +203,8 @@ entry: define ptx_device void @t4_global_u16(i16 %x) { entry: -;CHECK: mov.u32 r0, array_i16; -;CHECK-NEXT: st.global.u16 [r0], rh1; +;CHECK: mov.u32 r[[R0:[0-9]+]], array_i16; +;CHECK-NEXT: st.global.u16 [r[[R0]]], rh{{[0-9]+}}; ;CHECK-NEXT: ret; %i = getelementptr [10 x i16]* @array_i16, i16 0, i16 0 store i16 %x, i16* %i @@ -213,8 +213,8 @@ entry: define ptx_device void @t4_global_u32(i32 %x) { entry: -;CHECK: mov.u32 r0, array_i32; -;CHECK-NEXT: st.global.u32 [r0], r1; +;CHECK: mov.u32 r[[R0:[0-9]+]], array_i32; +;CHECK-NEXT: st.global.u32 [r[[R0]]], r{{[0-9]+}}; ;CHECK-NEXT: ret; %i = getelementptr [10 x i32]* @array_i32, i32 0, i32 0 store i32 %x, i32* %i @@ -223,8 +223,8 @@ entry: define ptx_device void @t4_global_u64(i64 %x) { entry: -;CHECK: mov.u32 r0, array_i64; -;CHECK-NEXT: st.global.u64 [r0], rd1; +;CHECK: mov.u32 r[[R0:[0-9]+]], array_i64; +;CHECK-NEXT: st.global.u64 [r[[R0]]], rd{{[0-9]+}}; ;CHECK-NEXT: ret; %i = getelementptr [10 x i64]* @array_i64, i32 0, i32 0 store i64 %x, i64* %i @@ -233,8 +233,8 @@ entry: define ptx_device void @t4_global_f32(float %x) { entry: -;CHECK: mov.u32 r0, array_float; -;CHECK-NEXT: st.global.f32 [r0], r1; +;CHECK: mov.u32 r[[R0:[0-9]+]], array_float; +;CHECK-NEXT: st.global.f32 [r[[R0]]], r{{[0-9]+}}; ;CHECK-NEXT: ret; %i = getelementptr [10 x float]* @array_float, i32 0, i32 0 store float %x, float* %i @@ -243,8 +243,8 @@ entry: define ptx_device void @t4_global_f64(double %x) { entry: -;CHECK: mov.u32 r0, array_double; -;CHECK-NEXT: st.global.f64 [r0], rd1; +;CHECK: mov.u32 r[[R0:[0-9]+]], array_double; +;CHECK-NEXT: st.global.f64 [r[[R0]]], rd{{[0-9]+}}; ;CHECK-NEXT: ret; %i = getelementptr [10 x double]* @array_double, i32 0, i32 0 store double %x, double* %i @@ -253,8 +253,8 @@ entry: define ptx_device void @t4_local_u16(i16 %x) { entry: -;CHECK: mov.u32 r0, array_local_i16; -;CHECK-NEXT: st.local.u16 [r0], rh1; +;CHECK: mov.u32 r[[R0:[0-9]+]], array_local_i16; +;CHECK-NEXT: st.local.u16 [r[[R0]]], rh{{[0-9]+}}; ;CHECK-NEXT: ret; %i = getelementptr [10 x i16] addrspace(2)* @array_local_i16, i32 0, i32 0 store i16 %x, i16 addrspace(2)* %i @@ -263,8 +263,8 @@ entry: define ptx_device void @t4_local_u32(i32 %x) { entry: -;CHECK: mov.u32 r0, array_local_i32; -;CHECK-NEXT: st.local.u32 [r0], r1; +;CHECK: mov.u32 r[[R0:[0-9]+]], array_local_i32; +;CHECK-NEXT: st.local.u32 [r[[R0]]], r{{[0-9]+}}; ;CHECK-NEXT: ret; %i = getelementptr [10 x i32] addrspace(2)* @array_local_i32, i32 0, i32 0 store i32 %x, i32 addrspace(2)* %i @@ -273,8 +273,8 @@ entry: define ptx_device void @t4_local_u64(i64 %x) { entry: -;CHECK: mov.u32 r0, array_local_i64; -;CHECK-NEXT: st.local.u64 [r0], rd1; +;CHECK: mov.u32 r[[R0:[0-9]+]], array_local_i64; +;CHECK-NEXT: st.local.u64 [r[[R0]]], rd{{[0-9]+}}; ;CHECK-NEXT: ret; %i = getelementptr [10 x i64] addrspace(2)* @array_local_i64, i32 0, i32 0 store i64 %x, i64 addrspace(2)* %i @@ -283,8 +283,8 @@ entry: define ptx_device void @t4_local_f32(float %x) { entry: -;CHECK: mov.u32 r0, array_local_float; -;CHECK-NEXT: st.local.f32 [r0], r1; +;CHECK: mov.u32 r[[R0:[0-9]+]], array_local_float; +;CHECK-NEXT: st.local.f32 [r[[R0]]], r{{[0-9]+}}; ;CHECK-NEXT: ret; %i = getelementptr [10 x float] addrspace(2)* @array_local_float, i32 0, i32 0 store float %x, float addrspace(2)* %i @@ -293,8 +293,8 @@ entry: define ptx_device void @t4_local_f64(double %x) { entry: -;CHECK: mov.u32 r0, array_local_double; -;CHECK-NEXT: st.local.f64 [r0], rd1; +;CHECK: mov.u32 r[[R0:[0-9]+]], array_local_double; +;CHECK-NEXT: st.local.f64 [r[[R0]]], rd{{[0-9]+}}; ;CHECK-NEXT: ret; %i = getelementptr [10 x double] addrspace(2)* @array_local_double, i32 0, i32 0 store double %x, double addrspace(2)* %i @@ -303,8 +303,8 @@ entry: define ptx_device void @t4_shared_u16(i16 %x) { entry: -;CHECK: mov.u32 r0, array_shared_i16; -;CHECK-NEXT: st.shared.u16 [r0], rh1; +;CHECK: mov.u32 r[[R0:[0-9]+]], array_shared_i16; +;CHECK-NEXT: st.shared.u16 [r[[R0]]], rh{{[0-9]+}}; ;CHECK-NEXT: ret; %i = getelementptr [10 x i16] addrspace(4)* @array_shared_i16, i32 0, i32 0 store i16 %x, i16 addrspace(4)* %i @@ -313,8 +313,8 @@ entry: define ptx_device void @t4_shared_u32(i32 %x) { entry: -;CHECK: mov.u32 r0, array_shared_i32; -;CHECK-NEXT: st.shared.u32 [r0], r1; +;CHECK: mov.u32 r[[R0:[0-9]+]], array_shared_i32; +;CHECK-NEXT: st.shared.u32 [r[[R0]]], r{{[0-9]+}}; ;CHECK-NEXT: ret; %i = getelementptr [10 x i32] addrspace(4)* @array_shared_i32, i32 0, i32 0 store i32 %x, i32 addrspace(4)* %i @@ -323,8 +323,8 @@ entry: define ptx_device void @t4_shared_u64(i64 %x) { entry: -;CHECK: mov.u32 r0, array_shared_i64; -;CHECK-NEXT: st.shared.u64 [r0], rd1; +;CHECK: mov.u32 r[[R0:[0-9]+]], array_shared_i64; +;CHECK-NEXT: st.shared.u64 [r[[R0]]], rd{{[0-9]+}}; ;CHECK-NEXT: ret; %i = getelementptr [10 x i64] addrspace(4)* @array_shared_i64, i32 0, i32 0 store i64 %x, i64 addrspace(4)* %i @@ -333,8 +333,8 @@ entry: define ptx_device void @t4_shared_f32(float %x) { entry: -;CHECK: mov.u32 r0, array_shared_float; -;CHECK-NEXT: st.shared.f32 [r0], r1; +;CHECK: mov.u32 r[[R0:[0-9]+]], array_shared_float; +;CHECK-NEXT: st.shared.f32 [r[[R0]]], r{{[0-9]+}}; ;CHECK-NEXT: ret; %i = getelementptr [10 x float] addrspace(4)* @array_shared_float, i32 0, i32 0 store float %x, float addrspace(4)* %i @@ -343,8 +343,8 @@ entry: define ptx_device void @t4_shared_f64(double %x) { entry: -;CHECK: mov.u32 r0, array_shared_double; -;CHECK-NEXT: st.shared.f64 [r0], rd1; +;CHECK: mov.u32 r[[R0:[0-9]+]], array_shared_double; +;CHECK-NEXT: st.shared.f64 [r[[R0]]], rd{{[0-9]+}}; ;CHECK-NEXT: ret; %i = getelementptr [10 x double] addrspace(4)* @array_shared_double, i32 0, i32 0 store double %x, double addrspace(4)* %i @@ -353,8 +353,8 @@ entry: define ptx_device void @t5_u16(i16 %x) { entry: -;CHECK: mov.u32 r0, array_i16; -;CHECK-NEXT: st.global.u16 [r0+2], rh1; +;CHECK: mov.u32 r[[R0:[0-9]+]], array_i16; +;CHECK-NEXT: st.global.u16 [r[[R0]]+2], rh{{[0-9]+}}; ;CHECK-NEXT: ret; %i = getelementptr [10 x i16]* @array_i16, i32 0, i32 1 store i16 %x, i16* %i @@ -363,8 +363,8 @@ entry: define ptx_device void @t5_u32(i32 %x) { entry: -;CHECK: mov.u32 r0, array_i32; -;CHECK-NEXT: st.global.u32 [r0+4], r1; +;CHECK: mov.u32 r[[R0:[0-9]+]], array_i32; +;CHECK-NEXT: st.global.u32 [r[[R0]]+4], r{{[0-9]+}}; ;CHECK-NEXT: ret; %i = getelementptr [10 x i32]* @array_i32, i32 0, i32 1 store i32 %x, i32* %i @@ -373,8 +373,8 @@ entry: define ptx_device void @t5_u64(i64 %x) { entry: -;CHECK: mov.u32 r0, array_i64; -;CHECK-NEXT: st.global.u64 [r0+8], rd1; +;CHECK: mov.u32 r[[R0:[0-9]+]], array_i64; +;CHECK-NEXT: st.global.u64 [r[[R0]]+8], rd{{[0-9]+}}; ;CHECK-NEXT: ret; %i = getelementptr [10 x i64]* @array_i64, i32 0, i32 1 store i64 %x, i64* %i @@ -383,8 +383,8 @@ entry: define ptx_device void @t5_f32(float %x) { entry: -;CHECK: mov.u32 r0, array_float; -;CHECK-NEXT: st.global.f32 [r0+4], r1; +;CHECK: mov.u32 r[[R0:[0-9]+]], array_float; +;CHECK-NEXT: st.global.f32 [r[[R0]]+4], r{{[0-9]+}}; ;CHECK-NEXT: ret; %i = getelementptr [10 x float]* @array_float, i32 0, i32 1 store float %x, float* %i @@ -393,8 +393,8 @@ entry: define ptx_device void @t5_f64(double %x) { entry: -;CHECK: mov.u32 r0, array_double; -;CHECK-NEXT: st.global.f64 [r0+8], rd1; +;CHECK: mov.u32 r[[R0:[0-9]+]], array_double; +;CHECK-NEXT: st.global.f64 [r[[R0]]+8], rd{{[0-9]+}}; ;CHECK-NEXT: ret; %i = getelementptr [10 x double]* @array_double, i32 0, i32 1 store double %x, double* %i diff --git a/test/CodeGen/PTX/sub.ll b/test/CodeGen/PTX/sub.ll index 4d55280..acef396 100644 --- a/test/CodeGen/PTX/sub.ll +++ b/test/CodeGen/PTX/sub.ll @@ -1,70 +1,70 @@ ; RUN: llc < %s -march=ptx32 | FileCheck %s define ptx_device i16 @t1_u16(i16 %x, i16 %y) { -; CHECK: sub.u16 rh0, rh1, rh2; +; CHECK: sub.u16 rh{{[0-9]+}}, rh{{[0-9]+}}, rh{{[0-9]+}}; ; CHECK-NEXT: ret; %z = sub i16 %x, %y ret i16 %z } define ptx_device i32 @t1_u32(i32 %x, i32 %y) { -; CHECK: sub.u32 r0, r1, r2; +; CHECK: sub.u32 r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}; ; CHECK-NEXT: ret; %z = sub i32 %x, %y ret i32 %z } define ptx_device i64 @t1_u64(i64 %x, i64 %y) { -; CHECK: sub.u64 rd0, rd1, rd2; +; CHECK: sub.u64 rd{{[0-9]+}}, rd{{[0-9]+}}, rd{{[0-9]+}}; ; CHECK-NEXT: ret; %z = sub i64 %x, %y ret i64 %z } define ptx_device float @t1_f32(float %x, float %y) { -; CHECK: sub.rn.f32 r0, r1, r2 +; CHECK: sub.rn.f32 r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}} ; CHECK-NEXT: ret; %z = fsub float %x, %y ret float %z } define ptx_device double @t1_f64(double %x, double %y) { -; CHECK: sub.rn.f64 rd0, rd1, rd2 +; CHECK: sub.rn.f64 rd{{[0-9]+}}, rd{{[0-9]+}}, rd{{[0-9]+}} ; CHECK-NEXT: ret; %z = fsub double %x, %y ret double %z } define ptx_device i16 @t2_u16(i16 %x) { -; CHECK: add.u16 rh0, rh1, -1; +; CHECK: add.u16 rh{{[0-9]+}}, rh{{[0-9]+}}, -1; ; CHECK-NEXT: ret; %z = sub i16 %x, 1 ret i16 %z } define ptx_device i32 @t2_u32(i32 %x) { -; CHECK: add.u32 r0, r1, -1; +; CHECK: add.u32 r{{[0-9]+}}, r{{[0-9]+}}, -1; ; CHECK-NEXT: ret; %z = sub i32 %x, 1 ret i32 %z } define ptx_device i64 @t2_u64(i64 %x) { -; CHECK: add.u64 rd0, rd1, -1; +; CHECK: add.u64 rd{{[0-9]+}}, rd{{[0-9]+}}, -1; ; CHECK-NEXT: ret; %z = sub i64 %x, 1 ret i64 %z } define ptx_device float @t2_f32(float %x) { -; CHECK: add.rn.f32 r0, r1, 0FBF800000; +; CHECK: add.rn.f32 r{{[0-9]+}}, r{{[0-9]+}}, 0FBF800000; ; CHECK-NEXT: ret; %z = fsub float %x, 1.0 ret float %z } define ptx_device double @t2_f64(double %x) { -; CHECK: add.rn.f64 rd0, rd1, 0DBFF0000000000000; +; CHECK: add.rn.f64 rd{{[0-9]+}}, rd{{[0-9]+}}, 0DBFF0000000000000; ; CHECK-NEXT: ret; %z = fsub double %x, 1.0 ret double %z -- cgit v1.1 From df214fa51715896d0cd5a407e8e4c57454619fc2 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Thu, 23 Jun 2011 18:15:17 +0000 Subject: Remove TargetOptions.h dependency from ARMSubtarget. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133738 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMSubtarget.cpp | 5 ----- lib/Target/ARM/ARMTargetMachine.cpp | 4 ++++ 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/Target/ARM/ARMSubtarget.cpp b/lib/Target/ARM/ARMSubtarget.cpp index c6f266b..f58cb54 100644 --- a/lib/Target/ARM/ARMSubtarget.cpp +++ b/lib/Target/ARM/ARMSubtarget.cpp @@ -15,7 +15,6 @@ #include "ARMGenSubtarget.inc" #include "ARMBaseRegisterInfo.h" #include "llvm/GlobalValue.h" -#include "llvm/Target/TargetOptions.h" #include "llvm/Support/CommandLine.h" #include "llvm/ADT/SmallVector.h" using namespace llvm; @@ -60,10 +59,6 @@ ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &FS, , CPUString("generic") , TargetTriple(TT) , TargetABI(ARM_ABI_APCS) { - // Default to soft float ABI - if (FloatABIType == FloatABI::Default) - FloatABIType = FloatABI::Soft; - // Determine default and user specified characteristics // When no arch is specified either by CPU or by attributes, make the default diff --git a/lib/Target/ARM/ARMTargetMachine.cpp b/lib/Target/ARM/ARMTargetMachine.cpp index 29aa4f7..088427f 100644 --- a/lib/Target/ARM/ARMTargetMachine.cpp +++ b/lib/Target/ARM/ARMTargetMachine.cpp @@ -85,6 +85,10 @@ ARMBaseTargetMachine::ARMBaseTargetMachine(const Target &T, JITInfo(), InstrItins(Subtarget.getInstrItineraryData()) { DefRelocModel = getRelocationModel(); + + // Default to soft float ABI + if (FloatABIType == FloatABI::Default) + FloatABIType = FloatABI::Soft; } ARMTargetMachine::ARMTargetMachine(const Target &T, const std::string &TT, -- cgit v1.1 From f05589d0430a543e8158b912dcb8117bf5cb376e Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Thu, 23 Jun 2011 18:15:47 +0000 Subject: Rename TargetOptions::StackAlignment to StackAlignmentOverride. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133739 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Target/TargetOptions.h | 4 ++-- lib/Target/TargetMachine.cpp | 4 ++-- lib/Target/X86/X86TargetMachine.cpp | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/llvm/Target/TargetOptions.h b/include/llvm/Target/TargetOptions.h index beed039..55d50d9 100644 --- a/include/llvm/Target/TargetOptions.h +++ b/include/llvm/Target/TargetOptions.h @@ -133,8 +133,8 @@ namespace llvm { /// as their parent function, etc.), using an alternate ABI if necessary. extern bool GuaranteedTailCallOpt; - /// StackAlignment - Override default stack alignment for target. - extern unsigned StackAlignment; + /// StackAlignmentOverride - Override default stack alignment for target. + extern unsigned StackAlignmentOverride; /// RealignStack - This flag indicates whether the stack should be /// automatically realigned, if needed. diff --git a/lib/Target/TargetMachine.cpp b/lib/Target/TargetMachine.cpp index 863b811..14044f2 100644 --- a/lib/Target/TargetMachine.cpp +++ b/lib/Target/TargetMachine.cpp @@ -43,7 +43,7 @@ namespace llvm { Reloc::Model RelocationModel; CodeModel::Model CMModel; bool GuaranteedTailCallOpt; - unsigned StackAlignment; + unsigned StackAlignmentOverride; bool RealignStack; bool DisableJumpTables; bool StrongPHIElim; @@ -183,7 +183,7 @@ EnableGuaranteedTailCallOpt("tailcallopt", static cl::opt OverrideStackAlignment("stack-alignment", cl::desc("Override default stack alignment"), - cl::location(StackAlignment), + cl::location(StackAlignmentOverride), cl::init(0)); static cl::opt EnableRealignStack("realign-stack", diff --git a/lib/Target/X86/X86TargetMachine.cpp b/lib/Target/X86/X86TargetMachine.cpp index 0b85469..c10bf1c 100644 --- a/lib/Target/X86/X86TargetMachine.cpp +++ b/lib/Target/X86/X86TargetMachine.cpp @@ -117,7 +117,7 @@ X86_64TargetMachine::X86_64TargetMachine(const Target &T, const std::string &TT, X86TargetMachine::X86TargetMachine(const Target &T, const std::string &TT, const std::string &FS, bool is64Bit) : LLVMTargetMachine(T, TT), - Subtarget(TT, FS, is64Bit, StackAlignment), + Subtarget(TT, FS, is64Bit, StackAlignmentOverride), FrameLowering(*this, Subtarget), ELFWriterInfo(is64Bit, true) { DefRelocModel = getRelocationModel(); -- cgit v1.1 From aeebc35886726c8d378033d7122f29feba5d4134 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Thu, 23 Jun 2011 18:24:27 +0000 Subject: Fix build for (some versions of?) MinGW. Patch by Ruben Van Boxem. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133741 91177308-0d34-0410-b5e6-96231b3b80d8 --- runtime/libprofile/GCDAProfiling.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/libprofile/GCDAProfiling.c b/runtime/libprofile/GCDAProfiling.c index 09a1aec..e066b22 100644 --- a/runtime/libprofile/GCDAProfiling.c +++ b/runtime/libprofile/GCDAProfiling.c @@ -89,7 +89,7 @@ static void recursive_mkdir(const char *filename) { pathname = malloc(i + 1); strncpy(pathname, filename, i); pathname[i] = '\0'; -#ifdef _MSC_VER +#ifdef _WIN32 _mkdir(pathname); #else mkdir(pathname, 0750); /* some of these will fail, ignore it. */ -- cgit v1.1 From 00805fae5b741a9732579050f60cedc7731f6256 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Thu, 23 Jun 2011 20:40:23 +0000 Subject: PR10180: Fix a instcombine crash with FP vectors. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133756 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/InstCombine/InstCombineSelect.cpp | 4 ++-- test/Transforms/InstCombine/select-crash.ll | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/lib/Transforms/InstCombine/InstCombineSelect.cpp b/lib/Transforms/InstCombine/InstCombineSelect.cpp index aeb3c3e..5733c20 100644 --- a/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -796,7 +796,7 @@ Instruction *InstCombiner::visitSelectInst(SelectInst &SI) { // So at this point we know we have (Y -> OtherAddOp): // select C, (add X, Y), (sub X, Z) Value *NegVal; // Compute -Z - if (SI.getType()->isFloatingPointTy()) { + if (SI.getType()->isFPOrFPVectorTy()) { NegVal = Builder->CreateFNeg(SubOp->getOperand(1)); } else { NegVal = Builder->CreateNeg(SubOp->getOperand(1)); @@ -810,7 +810,7 @@ Instruction *InstCombiner::visitSelectInst(SelectInst &SI) { Builder->CreateSelect(CondVal, NewTrueOp, NewFalseOp, SI.getName() + ".p"); - if (SI.getType()->isFloatingPointTy()) + if (SI.getType()->isFPOrFPVectorTy()) return BinaryOperator::CreateFAdd(SubOp->getOperand(0), NewSel); else return BinaryOperator::CreateAdd(SubOp->getOperand(0), NewSel); diff --git a/test/Transforms/InstCombine/select-crash.ll b/test/Transforms/InstCombine/select-crash.ll index 8ee3369..18af152 100644 --- a/test/Transforms/InstCombine/select-crash.ll +++ b/test/Transforms/InstCombine/select-crash.ll @@ -18,3 +18,15 @@ entry: %add94 = fadd double undef, %mul91 ret double %add94 } + +; PR10180: same crash, but with vectors +define <4 x float> @foo(i1 %b, <4 x float> %x, <4 x float> %y, <4 x float> %z) { +; CHECK: @foo +; CHECK: fsub <4 x float> +; CHECK: select +; CHECK: fadd <4 x float> + %a = fadd <4 x float> %x, %y + %sub = fsub <4 x float> %x, %z + %sel = select i1 %b, <4 x float> %a, <4 x float> %sub + ret <4 x float> %sel +} -- cgit v1.1 From a390a1aa48d8fa5085aa51b950f00d79dbb0c646 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Thu, 23 Jun 2011 21:07:47 +0000 Subject: Add support for movntil/movntiq mnemonics. Reported on llvmdev. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133759 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86InstrSSE.td | 4 ++-- test/MC/X86/x86-32-coverage.s | 24 ++++++++++++------------ test/MC/X86/x86-64.s | 12 ++++++++++++ 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/lib/Target/X86/X86InstrSSE.td b/lib/Target/X86/X86InstrSSE.td index 8377c3a..0bfc5e7 100644 --- a/lib/Target/X86/X86InstrSSE.td +++ b/lib/Target/X86/X86InstrSSE.td @@ -1991,11 +1991,11 @@ def : Pat<(alignednontemporalstore (v2i64 VR128:$src), addr:$dst), // There is no AVX form for instructions below this point def MOVNTImr : I<0xC3, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src), - "movnti\t{$src, $dst|$dst, $src}", + "movnti{l}\t{$src, $dst|$dst, $src}", [(nontemporalstore (i32 GR32:$src), addr:$dst)]>, TB, Requires<[HasSSE2]>; def MOVNTI_64mr : RI<0xC3, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src), - "movnti\t{$src, $dst|$dst, $src}", + "movnti{q}\t{$src, $dst|$dst, $src}", [(nontemporalstore (i64 GR64:$src), addr:$dst)]>, TB, Requires<[HasSSE2]>; } diff --git a/test/MC/X86/x86-32-coverage.s b/test/MC/X86/x86-32-coverage.s index d2dd78d..bdc54a6 100644 --- a/test/MC/X86/x86-32-coverage.s +++ b/test/MC/X86/x86-32-coverage.s @@ -503,7 +503,7 @@ // CHECK: ud2 ud2 -// CHECK: movnti %ecx, 3735928559(%ebx,%ecx,8) +// CHECK: movntil %ecx, 3735928559(%ebx,%ecx,8) movnti %ecx,0xdeadbeef(%ebx,%ecx,8) // CHECK: clflush 3735928559(%ebx,%ecx,8) @@ -4505,23 +4505,23 @@ // CHECK: encoding: [0xdf,0xea] fucomip %st(2),%st -// CHECK: movnti %ecx, 3735928559(%ebx,%ecx,8) +// CHECK: movntil %ecx, 3735928559(%ebx,%ecx,8) // CHECK: encoding: [0x0f,0xc3,0x8c,0xcb,0xef,0xbe,0xad,0xde] movnti %ecx,0xdeadbeef(%ebx,%ecx,8) -// CHECK: movnti %ecx, 69 +// CHECK: movntil %ecx, 69 // CHECK: encoding: [0x0f,0xc3,0x0d,0x45,0x00,0x00,0x00] movnti %ecx,0x45 -// CHECK: movnti %ecx, 32493 +// CHECK: movntil %ecx, 32493 // CHECK: encoding: [0x0f,0xc3,0x0d,0xed,0x7e,0x00,0x00] movnti %ecx,0x7eed -// CHECK: movnti %ecx, 3133065982 +// CHECK: movntil %ecx, 3133065982 // CHECK: encoding: [0x0f,0xc3,0x0d,0xfe,0xca,0xbe,0xba] movnti %ecx,0xbabecafe -// CHECK: movnti %ecx, 305419896 +// CHECK: movntil %ecx, 305419896 // CHECK: encoding: [0x0f,0xc3,0x0d,0x78,0x56,0x34,0x12] movnti %ecx,0x12345678 @@ -14177,19 +14177,19 @@ // CHECK: fucompi %st(2) fucomip %st(2),%st -// CHECK: movnti %ecx, 3735928559(%ebx,%ecx,8) +// CHECK: movntil %ecx, 3735928559(%ebx,%ecx,8) movnti %ecx,0xdeadbeef(%ebx,%ecx,8) -// CHECK: movnti %ecx, 69 - movnti %ecx,0x45 +// CHECK: movntil %ecx, 69 + movntil %ecx,0x45 -// CHECK: movnti %ecx, 32493 +// CHECK: movntil %ecx, 32493 movnti %ecx,0x7eed -// CHECK: movnti %ecx, 3133065982 +// CHECK: movntil %ecx, 3133065982 movnti %ecx,0xbabecafe -// CHECK: movnti %ecx, 305419896 +// CHECK: movntil %ecx, 305419896 movnti %ecx,0x12345678 // CHECK: clflush 3735928559(%ebx,%ecx,8) diff --git a/test/MC/X86/x86-64.s b/test/MC/X86/x86-64.s index 472748f..5074a1d 100644 --- a/test/MC/X86/x86-64.s +++ b/test/MC/X86/x86-64.s @@ -1136,3 +1136,15 @@ xsetbv // CHECK: xsetbv # encoding: [0x0f,0x01,0xd1] // CHECK: movd %rdi, %xmm0 // CHECK: encoding: [0x66,0x48,0x0f,0x6e,0xc7] movd %rdi,%xmm0 + +// CHECK: movntil %eax, (%rdi) +// CHECK: encoding: [0x0f,0xc3,0x07] +// CHECK: movntil +movntil %eax, (%rdi) +movnti %eax, (%rdi) + +// CHECK: movntiq %rax, (%rdi) +// CHECK: encoding: [0x48,0x0f,0xc3,0x07] +// CHECK: movntiq +movntiq %rax, (%rdi) +movnti %rax, (%rdi) -- cgit v1.1 From 44eb49c2a191108df801977c8e3dc03466c6c02a Mon Sep 17 00:00:00 2001 From: Jakub Staszak Date: Thu, 23 Jun 2011 21:45:20 +0000 Subject: Introduce BlockFrequency analysis for BasicBlocks. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133766 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Analysis/BranchProbabilityInfo.h | 10 ++++++++++ include/llvm/InitializePasses.h | 1 + include/llvm/Support/BranchProbability.h | 10 +++++++++- lib/Analysis/Analysis.cpp | 1 + lib/Analysis/BranchProbabilityInfo.cpp | 24 ++++++++++++++++++++++++ lib/Analysis/CMakeLists.txt | 1 + 6 files changed, 46 insertions(+), 1 deletion(-) diff --git a/include/llvm/Analysis/BranchProbabilityInfo.h b/include/llvm/Analysis/BranchProbabilityInfo.h index 5a17a76..e40d204 100644 --- a/include/llvm/Analysis/BranchProbabilityInfo.h +++ b/include/llvm/Analysis/BranchProbabilityInfo.h @@ -39,6 +39,9 @@ class BranchProbabilityInfo : public FunctionPass { // Get sum of the block successors' weights. uint32_t getSumForBlock(BasicBlock *BB) const; + // Get sum of the edge weights going to the BB block. + uint32_t getBackSumForBlock(BasicBlock *BB) const; + public: static char ID; @@ -71,6 +74,13 @@ public: // only iff SRC block has only one successor. BranchProbability getEdgeProbability(BasicBlock *Src, BasicBlock *Dst) const; + // Return a probability of getting to the DST block through SRC->DST edge. + // Returned value is a fraction between 0 (0% probability) and + // 1 (100% probability), however the value is never equal to 0, and can be 1 + // only iff DST block has only one predecesor. + BranchProbability getBackEdgeProbability(BasicBlock *Src, + BasicBlock *Dst) const; + // Print value between 0 (0% probability) and 1 (100% probability), // however the value is never equal to 0, and can be 1 only iff SRC block // has only one successor. diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h index 5efdcc9..5dfc4b3 100644 --- a/include/llvm/InitializePasses.h +++ b/include/llvm/InitializePasses.h @@ -65,6 +65,7 @@ void initializeArgPromotionPass(PassRegistry&); void initializeBasicAliasAnalysisPass(PassRegistry&); void initializeBasicCallGraphPass(PassRegistry&); void initializeBlockExtractorPassPass(PassRegistry&); +void initializeBlockFrequencyPass(PassRegistry&); void initializeBlockPlacementPass(PassRegistry&); void initializeBranchProbabilityInfoPass(PassRegistry&); void initializeBreakCriticalEdgesPass(PassRegistry&); diff --git a/include/llvm/Support/BranchProbability.h b/include/llvm/Support/BranchProbability.h index 7ba6491..c66d224 100644 --- a/include/llvm/Support/BranchProbability.h +++ b/include/llvm/Support/BranchProbability.h @@ -18,13 +18,17 @@ namespace llvm { -class raw_ostream; +template +class BlockFrequencyImpl; class BranchProbabilityInfo; class MachineBranchProbabilityInfo; class MachineBasicBlock; +class raw_ostream; // This class represents Branch Probability as a non-negative fraction. class BranchProbability { + template + friend class BlockFrequencyImpl; friend class BranchProbabilityInfo; friend class MachineBranchProbabilityInfo; friend class MachineBasicBlock; @@ -38,6 +42,10 @@ class BranchProbability { BranchProbability(uint32_t n, uint32_t d); public: + + uint32_t getNumerator() const { return N; } + uint32_t getDenominator() const { return D; } + raw_ostream &print(raw_ostream &OS) const; void dump() const; diff --git a/lib/Analysis/Analysis.cpp b/lib/Analysis/Analysis.cpp index e57ba78..71e0a83 100644 --- a/lib/Analysis/Analysis.cpp +++ b/lib/Analysis/Analysis.cpp @@ -23,6 +23,7 @@ void llvm::initializeAnalysis(PassRegistry &Registry) { initializeAliasSetPrinterPass(Registry); initializeNoAAPass(Registry); initializeBasicAliasAnalysisPass(Registry); + initializeBlockFrequencyPass(Registry); initializeBranchProbabilityInfoPass(Registry); initializeCFGViewerPass(Registry); initializeCFGPrinterPass(Registry); diff --git a/lib/Analysis/BranchProbabilityInfo.cpp b/lib/Analysis/BranchProbabilityInfo.cpp index 15059c7..263ea2c 100644 --- a/lib/Analysis/BranchProbabilityInfo.cpp +++ b/lib/Analysis/BranchProbabilityInfo.cpp @@ -279,6 +279,21 @@ uint32_t BranchProbabilityInfo::getSumForBlock(BasicBlock *BB) const { return Sum; } +uint32_t BranchProbabilityInfo::getBackSumForBlock(BasicBlock *BB) const { + uint32_t Sum = 0; + + for (pred_iterator I = pred_begin(BB), E = pred_end(BB); I != E; ++I) { + BasicBlock *Pred = *I; + uint32_t Weight = getEdgeWeight(Pred, BB); + uint32_t PrevSum = Sum; + + Sum += Weight; + assert(Sum > PrevSum); (void) PrevSum; + } + + return Sum; +} + bool BranchProbabilityInfo::isEdgeHot(BasicBlock *Src, BasicBlock *Dst) const { // Hot probability is at least 4/5 = 80% uint32_t Weight = getEdgeWeight(Src, Dst); @@ -345,6 +360,15 @@ getEdgeProbability(BasicBlock *Src, BasicBlock *Dst) const { return BranchProbability(N, D); } +BranchProbability BranchProbabilityInfo:: +getBackEdgeProbability(BasicBlock *Src, BasicBlock *Dst) const { + + uint32_t N = getEdgeWeight(Src, Dst); + uint32_t D = getBackSumForBlock(Dst); + + return BranchProbability(N, D); +} + raw_ostream & BranchProbabilityInfo::printEdgeProbability(raw_ostream &OS, BasicBlock *Src, BasicBlock *Dst) const { diff --git a/lib/Analysis/CMakeLists.txt b/lib/Analysis/CMakeLists.txt index 1a975bf..ab846a2 100644 --- a/lib/Analysis/CMakeLists.txt +++ b/lib/Analysis/CMakeLists.txt @@ -6,6 +6,7 @@ add_llvm_library(LLVMAnalysis AliasSetTracker.cpp Analysis.cpp BasicAliasAnalysis.cpp + BlockFrequency.cpp BranchProbabilityInfo.cpp CFGPrinter.cpp CaptureTracking.cpp -- cgit v1.1 From fd9533b4a35983d38804349efca8116788b311d9 Mon Sep 17 00:00:00 2001 From: Jakub Staszak Date: Thu, 23 Jun 2011 21:56:59 +0000 Subject: Missing files for the BlockFrequency analysis added. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133767 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Analysis/BlockFrequency.h | 53 +++++ include/llvm/Analysis/BlockFrequencyImpl.h | 336 +++++++++++++++++++++++++++++ lib/Analysis/BlockFrequency.cpp | 59 +++++ 3 files changed, 448 insertions(+) create mode 100644 include/llvm/Analysis/BlockFrequency.h create mode 100644 include/llvm/Analysis/BlockFrequencyImpl.h create mode 100644 lib/Analysis/BlockFrequency.cpp diff --git a/include/llvm/Analysis/BlockFrequency.h b/include/llvm/Analysis/BlockFrequency.h new file mode 100644 index 0000000..c4b1e08 --- /dev/null +++ b/include/llvm/Analysis/BlockFrequency.h @@ -0,0 +1,53 @@ +//========-------- BlockFrequency.h - Block Frequency Analysis -------========// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Loops should be simplified before this analysis. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_BLOCKFREQUENCY_H +#define LLVM_ANALYSIS_BLOCKFREQUENCY_H + +#include "llvm/Pass.h" +#include + +namespace llvm { + +class BranchProbabilityInfo; +template +class BlockFrequencyImpl; + +/// BlockFrequency pass uses BlockFrequencyImpl implementation to estimate +/// IR basic block frequencies. +class BlockFrequency : public FunctionPass { + + BlockFrequencyImpl *BFI; + +public: + static char ID; + + BlockFrequency(); + + ~BlockFrequency(); + + void getAnalysisUsage(AnalysisUsage &AU) const; + + bool runOnFunction(Function &F); + + /// getblockFreq - Return block frequency. Never return 0, value must be + /// positive. Please note that initial frequency is equal to 1024. It means + /// that we should not rely on the value itself, but only on the comparison to + /// the other block frequencies. We do this to avoid using of the floating + /// points. + uint32_t getBlockFreq(BasicBlock *BB); +}; + +} + +#endif diff --git a/include/llvm/Analysis/BlockFrequencyImpl.h b/include/llvm/Analysis/BlockFrequencyImpl.h new file mode 100644 index 0000000..7447e80 --- /dev/null +++ b/include/llvm/Analysis/BlockFrequencyImpl.h @@ -0,0 +1,336 @@ +//===---- BlockFrequencyImpl.h - Machine Block Frequency Implementation ---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Shared implementation of BlockFrequency for IR and Machine Instructions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_BLOCKFREQUENCYIMPL_H +#define LLVM_ANALYSIS_BLOCKFREQUENCYIMPL_H + +#include "llvm/BasicBlock.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/PostOrderIterator.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/Support/BranchProbability.h" +#include "llvm/Support/Debug.h" +#include +#include +#include + +namespace llvm { + + +class BlockFrequency; +/// BlockFrequencyImpl implements block frequency algorithm for IR and +/// Machine Instructions. Algorithm starts with value 1024 (START_FREQ) +/// for the entry block and then propagates frequencies using branch weights +/// from (Machine)BranchProbabilityInfo. LoopInfo is not required because +/// algorithm can find "backedges" by itself. +template +class BlockFrequencyImpl { + + DenseMap Freqs; + + BlockProbInfoT *BPI; + + FunctionT *Fn; + + typedef GraphTraits< Inverse > GT; + + static const uint32_t START_FREQ = 1024; + + std::string getBlockName(BasicBlock *BB) const { + return BB->getNameStr(); + } + + std::string getBlockName(MachineBasicBlock *MBB) const { + std::stringstream ss; + ss << "BB#" << MBB->getNumber(); + const BasicBlock *BB = MBB->getBasicBlock(); + + if (BB) + ss << " derived from LLVM BB " << BB->getNameStr(); + + return ss.str(); + } + + void setBlockFreq(BlockT *BB, uint32_t Freq) { + Freqs[BB] = Freq; + DEBUG(dbgs() << "Frequency(" << getBlockName(BB) << ") = " << Freq << "\n"); + } + + /// getEdgeFreq - Return edge frequency based on SRC frequency and Src -> Dst + /// edge probability. + uint32_t getEdgeFreq(BlockT *Src, BlockT *Dst) const { + BranchProbability Prob = BPI->getEdgeProbability(Src, Dst); + uint64_t N = Prob.getNumerator(); + uint64_t D = Prob.getDenominator(); + uint64_t Res = (N * getBlockFreq(Src)) / D; + + assert(Res <= UINT32_MAX); + return (uint32_t) Res; + } + + /// incBlockFreq - Increase BB block frequency by FREQ. + /// + void incBlockFreq(BlockT *BB, uint32_t Freq) { + Freqs[BB] += Freq; + DEBUG(dbgs() << "Frequency(" << getBlockName(BB) << ") += " << Freq + << " --> " << Freqs[BB] << "\n"); + } + + /// divBlockFreq - Divide BB block frequency by PROB. If Prob = 0 do nothing. + /// + void divBlockFreq(BlockT *BB, BranchProbability Prob) { + uint64_t N = Prob.getNumerator(); + assert(N && "Illegal division by zero!"); + uint64_t D = Prob.getDenominator(); + uint64_t Freq = (Freqs[BB] * D) / N; + + // Should we assert it? + if (Freq > UINT32_MAX) + Freq = UINT32_MAX; + + Freqs[BB] = (uint32_t) Freq; + DEBUG(dbgs() << "Frequency(" << getBlockName(BB) << ") /= (" << Prob + << ") --> " << Freqs[BB] << "\n"); + } + + // All blocks in postorder. + std::vector POT; + + // Map Block -> Position in reverse-postorder list. + DenseMap RPO; + + // Cycle Probability for each bloch. + DenseMap CycleProb; + + // (reverse-)postorder traversal iterators. + typedef typename std::vector::iterator pot_iterator; + typedef typename std::vector::reverse_iterator rpot_iterator; + + pot_iterator pot_begin() { return POT.begin(); } + pot_iterator pot_end() { return POT.end(); } + + rpot_iterator rpot_begin() { return POT.rbegin(); } + rpot_iterator rpot_end() { return POT.rend(); } + + rpot_iterator rpot_at(BlockT *BB) { + rpot_iterator I = rpot_begin(); + unsigned idx = RPO[BB]; + assert(idx); + std::advance(I, idx - 1); + + assert(*I == BB); + return I; + } + + + /// isReachable - Returns if BB block is reachable from the entry. + /// + bool isReachable(BlockT *BB) { + return RPO.count(BB); + } + + /// isBackedge - Return if edge Src -> Dst is a backedge. + /// + bool isBackedge(BlockT *Src, BlockT *Dst) { + assert(isReachable(Src)); + assert(isReachable(Dst)); + + unsigned a = RPO[Src]; + unsigned b = RPO[Dst]; + + return a > b; + } + + /// getSingleBlockPred - return single BB block predecessor or NULL if + /// BB has none or more predecessors. + BlockT *getSingleBlockPred(BlockT *BB) { + typename GT::ChildIteratorType + PI = GraphTraits< Inverse >::child_begin(BB), + PE = GraphTraits< Inverse >::child_end(BB); + + if (PI == PE) + return 0; + + BlockT *Pred = *PI; + + ++PI; + if (PI != PE) + return 0; + + return Pred; + } + + void doBlock(BlockT *BB, BlockT *LoopHead, + SmallPtrSet &BlocksInLoop) { + + DEBUG(dbgs() << "doBlock(" << getBlockName(BB) << ")\n"); + setBlockFreq(BB, 0); + + if (BB == LoopHead) { + setBlockFreq(BB, START_FREQ); + return; + } + + if(BlockT *Pred = getSingleBlockPred(BB)) { + if (BlocksInLoop.count(Pred)) + setBlockFreq(BB, getEdgeFreq(Pred, BB)); + // TODO: else? irreducible, ignore it for now. + return; + } + + bool isInLoop = false; + bool isLoopHead = false; + + for (typename GT::ChildIteratorType + PI = GraphTraits< Inverse >::child_begin(BB), + PE = GraphTraits< Inverse >::child_end(BB); + PI != PE; ++PI) { + BlockT *Pred = *PI; + + if (isReachable(Pred) && isBackedge(Pred, BB)) { + isLoopHead = true; + } else if (BlocksInLoop.count(Pred)) { + incBlockFreq(BB, getEdgeFreq(Pred, BB)); + isInLoop = true; + } + // TODO: else? irreducible. + } + + if (!isInLoop) + return; + + if (!isLoopHead) + return; + + assert(START_FREQ >= CycleProb[BB]); + divBlockFreq(BB, BranchProbability(START_FREQ - CycleProb[BB], START_FREQ)); + } + + /// doLoop - Propagate block frequency down throught the loop. + void doLoop(BlockT *Head, BlockT *Tail) { + DEBUG(dbgs() << "doLoop(" << getBlockName(Head) << ", " + << getBlockName(Tail) << ")\n"); + + SmallPtrSet BlocksInLoop; + + for (rpot_iterator I = rpot_at(Head), E = rpot_end(); I != E; ++I) { + BlockT *BB = *I; + doBlock(BB, Head, BlocksInLoop); + + BlocksInLoop.insert(BB); + } + + // Compute loop's cyclic probability using backedges probabilities. + for (typename GT::ChildIteratorType + PI = GraphTraits< Inverse >::child_begin(Head), + PE = GraphTraits< Inverse >::child_end(Head); + PI != PE; ++PI) { + BlockT *Pred = *PI; + assert(Pred); + if (isReachable(Pred) && isBackedge(Pred, Head)) { + BranchProbability Prob = BPI->getBackEdgeProbability(Pred, Head); + uint64_t N = Prob.getNumerator(); + uint64_t D = Prob.getDenominator(); + uint64_t Res = (N * START_FREQ) / D; + + // CycleProb[Head] += getEdgeFreq(Pred, Head); + assert(Res <= UINT32_MAX); + CycleProb[Head] += (uint32_t) Res; + } + } + } + + + friend class BlockFrequency; + + void doFunction(FunctionT *fn, BlockProbInfoT *bpi) { + Fn = fn; + BPI = bpi; + + // Clear everything. + RPO.clear(); + POT.clear(); + CycleProb.clear(); + Freqs.clear(); + + BlockT *EntryBlock = fn->begin(); + + copy(po_begin(EntryBlock), po_end(EntryBlock), back_inserter(POT)); + + unsigned RPOidx = 0; + for (rpot_iterator I = rpot_begin(), E = rpot_end(); I != E; ++I) { + BlockT *BB = *I; + RPO[BB] = ++RPOidx; + DEBUG(dbgs() << "RPO[" << getBlockName(BB) << "] = " << RPO[BB] << "\n"); + } + + // Travel over all blocks in postorder. + for (pot_iterator I = pot_begin(), E = pot_end(); I != E; ++I) { + BlockT *BB = *I; + BlockT *LastTail = 0; + DEBUG(dbgs() << "POT: " << getBlockName(BB) << "\n"); + + for (typename GT::ChildIteratorType + PI = GraphTraits< Inverse >::child_begin(BB), + PE = GraphTraits< Inverse >::child_end(BB); + PI != PE; ++PI) { + + BlockT *Pred = *PI; + if (isReachable(Pred) && isBackedge(Pred, BB) + && (!LastTail || RPO[Pred] > RPO[LastTail])) + LastTail = Pred; + } + + if (LastTail) + doLoop(BB, LastTail); + } + + // At the end assume the whole function as a loop, and travel over it once + // again. + doLoop(*(rpot_begin()), *(pot_begin())); + } + +public: + /// getBlockFreq - Return block frequency. Never return 0, value must be + /// positive. + uint32_t getBlockFreq(BlockT *BB) const { + typename DenseMap::const_iterator I = Freqs.find(BB); + if (I != Freqs.end()) + return I->second ? I->second : 1; + return 1; + } + + void print(raw_ostream &OS) const { + OS << "\n\n---- Block Freqs ----\n"; + for (typename FunctionT::iterator I = Fn->begin(), E = Fn->end(); I != E;) { + BlockT *BB = I++; + OS << " " << getBlockName(BB) << " = " << getBlockFreq(BB) << "\n"; + + for (typename GraphTraits::ChildIteratorType + SI = GraphTraits::child_begin(BB), + SE = GraphTraits::child_end(BB); SI != SE; ++SI) { + BlockT *Succ = *SI; + OS << " " << getBlockName(BB) << " -> " << getBlockName(Succ) + << " = " << getEdgeFreq(BB, Succ) << "\n"; + } + } + } + + void dump() const { + print(dbgs()); + } +}; + +} + +#endif diff --git a/lib/Analysis/BlockFrequency.cpp b/lib/Analysis/BlockFrequency.cpp new file mode 100644 index 0000000..4b86d1d --- /dev/null +++ b/lib/Analysis/BlockFrequency.cpp @@ -0,0 +1,59 @@ +//=======-------- BlockFrequency.cpp - Block Frequency Analysis -------=======// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Loops should be simplified before this analysis. +// +//===----------------------------------------------------------------------===// + +#include "llvm/InitializePasses.h" +#include "llvm/Analysis/BlockFrequencyImpl.h" +#include "llvm/Analysis/BlockFrequency.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/Passes.h" +#include "llvm/Analysis/BranchProbabilityInfo.h" + +using namespace llvm; + +INITIALIZE_PASS_BEGIN(BlockFrequency, "block-freq", "Block Frequency Analysis", + true, true) +INITIALIZE_PASS_DEPENDENCY(BranchProbabilityInfo) +INITIALIZE_PASS_END(BlockFrequency, "block-freq", "Block Frequency Analysis", + true, true) + +char BlockFrequency::ID = 0; + + +BlockFrequency::BlockFrequency() : FunctionPass(ID) { + initializeBlockFrequencyPass(*PassRegistry::getPassRegistry()); + BFI = new BlockFrequencyImpl(); +} + +BlockFrequency::~BlockFrequency() { + delete BFI; +} + +void BlockFrequency::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + AU.setPreservesAll(); +} + +bool BlockFrequency::runOnFunction(Function &F) { + BranchProbabilityInfo &BPI = getAnalysis(); + BFI->doFunction(&F, &BPI); + return false; +} + +/// getblockFreq - Return block frequency. Never return 0, value must be +/// positive. Please note that initial frequency is equal to 1024. It means that +/// we should not rely on the value itself, but only on the comparison to the +/// other block frequencies. We do this to avoid using of floating points. +/// +uint32_t BlockFrequency::getBlockFreq(BasicBlock *BB) { + return BFI->getBlockFreq(BB); +} -- cgit v1.1 From 0edb05b9e4a63d469a6cc9e15fa0dc8de7ee1cdf Mon Sep 17 00:00:00 2001 From: Jim Grosbach Date: Thu, 23 Jun 2011 22:29:00 +0000 Subject: Tidy up. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133770 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/MC/MachObjectWriter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/MC/MachObjectWriter.cpp b/lib/MC/MachObjectWriter.cpp index 0d80514..073a41e 100644 --- a/lib/MC/MachObjectWriter.cpp +++ b/lib/MC/MachObjectWriter.cpp @@ -123,7 +123,7 @@ private: const MCAsmLayout &Layout) const; uint64_t getFragmentAddress(const MCFragment *Fragment, - const MCAsmLayout &Layout) const { + const MCAsmLayout &Layout) const { return getSectionAddress(Fragment->getParent()) + Layout.getFragmentOffset(Fragment); } -- cgit v1.1 From 66dddd1da3e036d05f94df82221a97b7d26e3498 Mon Sep 17 00:00:00 2001 From: Jakub Staszak Date: Thu, 23 Jun 2011 23:52:11 +0000 Subject: Calculate backedge probability correctly. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133776 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Analysis/BlockFrequencyImpl.h | 17 +++++++++++++---- include/llvm/Analysis/BranchProbabilityInfo.h | 10 ---------- lib/Analysis/BranchProbabilityInfo.cpp | 24 ------------------------ 3 files changed, 13 insertions(+), 38 deletions(-) diff --git a/include/llvm/Analysis/BlockFrequencyImpl.h b/include/llvm/Analysis/BlockFrequencyImpl.h index 7447e80..cef375f 100644 --- a/include/llvm/Analysis/BlockFrequencyImpl.h +++ b/include/llvm/Analysis/BlockFrequencyImpl.h @@ -133,6 +133,15 @@ class BlockFrequencyImpl { } + /// Return a probability of getting to the DST block through SRC->DST edge. + /// + BranchProbability getBackEdgeProbability(BlockT *Src, BlockT *Dst) const { + uint32_t N = getEdgeFreq(Src, Dst); + uint32_t D = getBlockFreq(Dst); + + return BranchProbability(N, D); + } + /// isReachable - Returns if BB block is reachable from the entry. /// bool isReachable(BlockT *BB) { @@ -213,7 +222,9 @@ class BlockFrequencyImpl { return; assert(START_FREQ >= CycleProb[BB]); - divBlockFreq(BB, BranchProbability(START_FREQ - CycleProb[BB], START_FREQ)); + uint32_t CProb = CycleProb[BB]; + uint32_t Numerator = START_FREQ - CProb ? START_FREQ - CProb : 1; + divBlockFreq(BB, BranchProbability(Numerator, START_FREQ)); } /// doLoop - Propagate block frequency down throught the loop. @@ -238,19 +249,17 @@ class BlockFrequencyImpl { BlockT *Pred = *PI; assert(Pred); if (isReachable(Pred) && isBackedge(Pred, Head)) { - BranchProbability Prob = BPI->getBackEdgeProbability(Pred, Head); + BranchProbability Prob = getBackEdgeProbability(Pred, Head); uint64_t N = Prob.getNumerator(); uint64_t D = Prob.getDenominator(); uint64_t Res = (N * START_FREQ) / D; - // CycleProb[Head] += getEdgeFreq(Pred, Head); assert(Res <= UINT32_MAX); CycleProb[Head] += (uint32_t) Res; } } } - friend class BlockFrequency; void doFunction(FunctionT *fn, BlockProbInfoT *bpi) { diff --git a/include/llvm/Analysis/BranchProbabilityInfo.h b/include/llvm/Analysis/BranchProbabilityInfo.h index e40d204..5a17a76 100644 --- a/include/llvm/Analysis/BranchProbabilityInfo.h +++ b/include/llvm/Analysis/BranchProbabilityInfo.h @@ -39,9 +39,6 @@ class BranchProbabilityInfo : public FunctionPass { // Get sum of the block successors' weights. uint32_t getSumForBlock(BasicBlock *BB) const; - // Get sum of the edge weights going to the BB block. - uint32_t getBackSumForBlock(BasicBlock *BB) const; - public: static char ID; @@ -74,13 +71,6 @@ public: // only iff SRC block has only one successor. BranchProbability getEdgeProbability(BasicBlock *Src, BasicBlock *Dst) const; - // Return a probability of getting to the DST block through SRC->DST edge. - // Returned value is a fraction between 0 (0% probability) and - // 1 (100% probability), however the value is never equal to 0, and can be 1 - // only iff DST block has only one predecesor. - BranchProbability getBackEdgeProbability(BasicBlock *Src, - BasicBlock *Dst) const; - // Print value between 0 (0% probability) and 1 (100% probability), // however the value is never equal to 0, and can be 1 only iff SRC block // has only one successor. diff --git a/lib/Analysis/BranchProbabilityInfo.cpp b/lib/Analysis/BranchProbabilityInfo.cpp index 263ea2c..15059c7 100644 --- a/lib/Analysis/BranchProbabilityInfo.cpp +++ b/lib/Analysis/BranchProbabilityInfo.cpp @@ -279,21 +279,6 @@ uint32_t BranchProbabilityInfo::getSumForBlock(BasicBlock *BB) const { return Sum; } -uint32_t BranchProbabilityInfo::getBackSumForBlock(BasicBlock *BB) const { - uint32_t Sum = 0; - - for (pred_iterator I = pred_begin(BB), E = pred_end(BB); I != E; ++I) { - BasicBlock *Pred = *I; - uint32_t Weight = getEdgeWeight(Pred, BB); - uint32_t PrevSum = Sum; - - Sum += Weight; - assert(Sum > PrevSum); (void) PrevSum; - } - - return Sum; -} - bool BranchProbabilityInfo::isEdgeHot(BasicBlock *Src, BasicBlock *Dst) const { // Hot probability is at least 4/5 = 80% uint32_t Weight = getEdgeWeight(Src, Dst); @@ -360,15 +345,6 @@ getEdgeProbability(BasicBlock *Src, BasicBlock *Dst) const { return BranchProbability(N, D); } -BranchProbability BranchProbabilityInfo:: -getBackEdgeProbability(BasicBlock *Src, BasicBlock *Dst) const { - - uint32_t N = getEdgeWeight(Src, Dst); - uint32_t D = getBackSumForBlock(Dst); - - return BranchProbability(N, D); -} - raw_ostream & BranchProbabilityInfo::printEdgeProbability(raw_ostream &OS, BasicBlock *Src, BasicBlock *Dst) const { -- cgit v1.1 From a347f85dbeee37a7f2bb68df1a7d4cdfbb7b576d Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Fri, 24 Jun 2011 01:44:41 +0000 Subject: Starting to refactor Target to separate out code that's needed to fully describe target machine from those that are only needed by codegen. The goal is to sink the essential target description into MC layer so we can start building MC based tools without needing to link in the entire codegen. First step is to refactor TargetRegisterInfo. This patch added a base class MCRegisterInfo which TargetRegisterInfo is derived from. Changed TableGen to separate register description from the rest of the stuff. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133782 91177308-0d34-0410-b5e6-96231b3b80d8 --- Makefile.rules | 9 +- include/llvm/MC/MCRegisterInfo.h | 123 ++++++++++++++++++ include/llvm/Target/TargetRegisterInfo.h | 100 +++------------ include/llvm/Target/TargetRegistry.h | 39 +++++- lib/CodeGen/RegisterClassInfo.h | 2 +- lib/Target/ARM/ARMBaseRegisterInfo.cpp | 7 +- lib/Target/ARM/CMakeLists.txt | 5 +- lib/Target/ARM/Makefile | 7 +- lib/Target/Alpha/AlphaRegisterInfo.cpp | 9 +- lib/Target/Alpha/CMakeLists.txt | 5 +- lib/Target/Alpha/Makefile | 6 +- lib/Target/Blackfin/BlackfinRegisterInfo.cpp | 8 +- lib/Target/Blackfin/CMakeLists.txt | 5 +- lib/Target/Blackfin/Makefile | 5 +- lib/Target/CellSPU/Makefile | 3 +- lib/Target/CellSPU/SPURegisterInfo.cpp | 7 +- lib/Target/MBlaze/CMakeLists.txt | 5 +- lib/Target/MBlaze/MBlazeRegisterInfo.cpp | 9 +- lib/Target/MBlaze/Makefile | 13 +- lib/Target/MSP430/CMakeLists.txt | 5 +- lib/Target/MSP430/MSP430RegisterInfo.cpp | 7 +- lib/Target/MSP430/Makefile | 3 +- lib/Target/Mips/CMakeLists.txt | 5 +- lib/Target/Mips/Makefile | 3 +- lib/Target/Mips/MipsRegisterInfo.cpp | 7 +- lib/Target/PTX/CMakeLists.txt | 5 +- lib/Target/PTX/Makefile | 1 + lib/Target/PTX/PTXRegisterInfo.cpp | 6 + lib/Target/PTX/PTXRegisterInfo.h | 2 +- lib/Target/PowerPC/CMakeLists.txt | 5 +- lib/Target/PowerPC/Makefile | 1 + lib/Target/PowerPC/PPCRegisterInfo.cpp | 7 +- lib/Target/Sparc/CMakeLists.txt | 5 +- lib/Target/Sparc/Makefile | 3 +- lib/Target/Sparc/SparcRegisterInfo.cpp | 8 +- lib/Target/SystemZ/CMakeLists.txt | 5 +- lib/Target/SystemZ/Makefile | 3 +- lib/Target/SystemZ/SystemZRegisterInfo.cpp | 8 +- lib/Target/TargetRegisterInfo.cpp | 9 +- lib/Target/X86/CMakeLists.txt | 5 +- lib/Target/X86/Makefile | 9 +- lib/Target/X86/TargetDesc/Makefile | 16 +++ lib/Target/X86/TargetDesc/X86TargetDesc.cpp | 23 ++++ lib/Target/X86/TargetDesc/X86TargetDesc.h | 17 +++ lib/Target/X86/X86.h | 5 +- lib/Target/X86/X86RegisterInfo.cpp | 7 +- lib/Target/XCore/CMakeLists.txt | 6 +- lib/Target/XCore/Makefile | 3 +- lib/Target/XCore/XCoreRegisterInfo.cpp | 9 +- utils/TableGen/RegisterInfoEmitter.cpp | 185 +++++++++++++++++---------- utils/TableGen/RegisterInfoEmitter.h | 3 + utils/TableGen/TableGen.cpp | 20 +-- 52 files changed, 502 insertions(+), 271 deletions(-) create mode 100644 include/llvm/MC/MCRegisterInfo.h create mode 100644 lib/Target/X86/TargetDesc/Makefile create mode 100644 lib/Target/X86/TargetDesc/X86TargetDesc.cpp create mode 100644 lib/Target/X86/TargetDesc/X86TargetDesc.h diff --git a/Makefile.rules b/Makefile.rules index 98c72c0..2acadd8 100644 --- a/Makefile.rules +++ b/Makefile.rules @@ -1725,15 +1725,20 @@ $(ObjDir)/%GenRegisterNames.inc.tmp : %.td $(ObjDir)/.dir $(Echo) "Building $( + +namespace llvm { + +/// TargetRegisterDesc - This record contains all of the information known about +/// a particular register. The Overlaps field contains a pointer to a zero +/// terminated array of registers that this register aliases, starting with +/// itself. This is needed for architectures like X86 which have AL alias AX +/// alias EAX. The SubRegs field is a zero terminated array of registers that +/// are sub-registers of the specific register, e.g. AL, AH are sub-registers of +/// AX. The SuperRegs field is a zero terminated array of registers that are +/// super-registers of the specific register, e.g. RAX, EAX, are super-registers +/// of AX. +/// +struct TargetRegisterDesc { + const char *Name; // Printable name for the reg (for debugging) + const unsigned *Overlaps; // Overlapping registers, described above + const unsigned *SubRegs; // Sub-register set, described above + const unsigned *SuperRegs; // Super-register set, described above +}; + +/// MCRegisterInfo base class - We assume that the target defines a static +/// array of TargetRegisterDesc objects that represent all of the machine +/// registers that the target has. As such, we simply have to track a pointer +/// to this array so that we can turn register number into a register +/// descriptor. +/// +class MCRegisterInfo { +private: + const TargetRegisterDesc *Desc; // Pointer to the descriptor array + unsigned NumRegs; // Number of entries in the array + +public: + /// InitMCRegisterInfo - Initialize MCRegisterInfo, called by TableGen + /// auto-generated routines. *DO NOT USE*. + void InitMCRegisterInfo(const TargetRegisterDesc *D, unsigned NR) { + Desc = D; + NumRegs = NR; + } + + const TargetRegisterDesc &operator[](unsigned RegNo) const { + assert(RegNo < NumRegs && + "Attempting to access record for invalid register number!"); + return Desc[RegNo]; + } + + /// Provide a get method, equivalent to [], but more useful if we have a + /// pointer to this object. + /// + const TargetRegisterDesc &get(unsigned RegNo) const { + return operator[](RegNo); + } + + /// getAliasSet - Return the set of registers aliased by the specified + /// register, or a null list of there are none. The list returned is zero + /// terminated. + /// + const unsigned *getAliasSet(unsigned RegNo) const { + // The Overlaps set always begins with Reg itself. + return get(RegNo).Overlaps + 1; + } + + /// getOverlaps - Return a list of registers that overlap Reg, including + /// itself. This is the same as the alias set except Reg is included in the + /// list. + /// These are exactly the registers in { x | regsOverlap(x, Reg) }. + /// + const unsigned *getOverlaps(unsigned RegNo) const { + return get(RegNo).Overlaps; + } + + /// getSubRegisters - Return the list of registers that are sub-registers of + /// the specified register, or a null list of there are none. The list + /// returned is zero terminated and sorted according to super-sub register + /// relations. e.g. X86::RAX's sub-register list is EAX, AX, AL, AH. + /// + const unsigned *getSubRegisters(unsigned RegNo) const { + return get(RegNo).SubRegs; + } + + /// getSuperRegisters - Return the list of registers that are super-registers + /// of the specified register, or a null list of there are none. The list + /// returned is zero terminated and sorted according to super-sub register + /// relations. e.g. X86::AL's super-register list is AX, EAX, RAX. + /// + const unsigned *getSuperRegisters(unsigned RegNo) const { + return get(RegNo).SuperRegs; + } + + /// getName - Return the human-readable symbolic target-specific name for the + /// specified physical register. + const char *getName(unsigned RegNo) const { + return get(RegNo).Name; + } + + /// getNumRegs - Return the number of registers this target has (useful for + /// sizing arrays holding per register information) + unsigned getNumRegs() const { + return NumRegs; + } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h index 840b048..d50bfe7 100644 --- a/include/llvm/Target/TargetRegisterInfo.h +++ b/include/llvm/Target/TargetRegisterInfo.h @@ -16,6 +16,7 @@ #ifndef LLVM_TARGET_TARGETREGISTERINFO_H #define LLVM_TARGET_TARGETREGISTERINFO_H +#include "llvm/MC/MCRegisterInfo.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/ValueTypes.h" #include "llvm/ADT/ArrayRef.h" @@ -32,25 +33,6 @@ class RegScavenger; template class SmallVectorImpl; class raw_ostream; -/// TargetRegisterDesc - This record contains all of the information known about -/// a particular register. The Overlaps field contains a pointer to a zero -/// terminated array of registers that this register aliases, starting with -/// itself. This is needed for architectures like X86 which have AL alias AX -/// alias EAX. The SubRegs field is a zero terminated array of registers that -/// are sub-registers of the specific register, e.g. AL, AH are sub-registers of -/// AX. The SuperRegs field is a zero terminated array of registers that are -/// super-registers of the specific register, e.g. RAX, EAX, are super-registers -/// of AX. -/// -struct TargetRegisterDesc { - const char *Name; // Printable name for the reg (for debugging) - const unsigned *Overlaps; // Overlapping registers, described above - const unsigned *SubRegs; // Sub-register set, described above - const unsigned *SuperRegs; // Super-register set, described above - unsigned CostPerUse; // Extra cost of instructions using register. - bool inAllocatableClass; // Register belongs to an allocatable regclass. -}; - class TargetRegisterClass { public: typedef const unsigned* iterator; @@ -274,6 +256,12 @@ public: bool isAllocatable() const { return Allocatable; } }; +/// TargetRegisterInfoDesc - Extra information, not in MCRegisterDesc, about +/// registers. These are used by codegen, not by MC. +struct TargetRegisterInfoDesc { + unsigned CostPerUse; // Extra cost of instructions using register. + bool inAllocatableClass; // Register belongs to an allocatable regclass. +}; /// TargetRegisterInfo base class - We assume that the target defines a static /// array of TargetRegisterDesc objects that represent all of the machine @@ -281,20 +269,17 @@ public: /// to this array so that we can turn register number into a register /// descriptor. /// -class TargetRegisterInfo { +class TargetRegisterInfo : public MCRegisterInfo { public: typedef const TargetRegisterClass * const * regclass_iterator; private: - const TargetRegisterDesc *Desc; // Pointer to the descriptor array + const TargetRegisterInfoDesc *InfoDesc; // Extra desc array for codegen const char *const *SubRegIndexNames; // Names of subreg indexes. - unsigned NumRegs; // Number of entries in the array - regclass_iterator RegClassBegin, RegClassEnd; // List of regclasses - int CallFrameSetupOpcode, CallFrameDestroyOpcode; protected: - TargetRegisterInfo(const TargetRegisterDesc *D, unsigned NR, + TargetRegisterInfo(const TargetRegisterInfoDesc *ID, regclass_iterator RegClassBegin, regclass_iterator RegClassEnd, const char *const *subregindexnames, @@ -379,71 +364,16 @@ public: BitVector getAllocatableSet(const MachineFunction &MF, const TargetRegisterClass *RC = NULL) const; - const TargetRegisterDesc &operator[](unsigned RegNo) const { - assert(RegNo < NumRegs && - "Attempting to access record for invalid register number!"); - return Desc[RegNo]; - } - - /// Provide a get method, equivalent to [], but more useful if we have a - /// pointer to this object. - /// - const TargetRegisterDesc &get(unsigned RegNo) const { - return operator[](RegNo); - } - - /// getAliasSet - Return the set of registers aliased by the specified - /// register, or a null list of there are none. The list returned is zero - /// terminated. - /// - const unsigned *getAliasSet(unsigned RegNo) const { - // The Overlaps set always begins with Reg itself. - return get(RegNo).Overlaps + 1; - } - - /// getOverlaps - Return a list of registers that overlap Reg, including - /// itself. This is the same as the alias set except Reg is included in the - /// list. - /// These are exactly the registers in { x | regsOverlap(x, Reg) }. - /// - const unsigned *getOverlaps(unsigned RegNo) const { - return get(RegNo).Overlaps; - } - - /// getSubRegisters - Return the list of registers that are sub-registers of - /// the specified register, or a null list of there are none. The list - /// returned is zero terminated and sorted according to super-sub register - /// relations. e.g. X86::RAX's sub-register list is EAX, AX, AL, AH. - /// - const unsigned *getSubRegisters(unsigned RegNo) const { - return get(RegNo).SubRegs; - } - - /// getSuperRegisters - Return the list of registers that are super-registers - /// of the specified register, or a null list of there are none. The list - /// returned is zero terminated and sorted according to super-sub register - /// relations. e.g. X86::AL's super-register list is AX, EAX, RAX. - /// - const unsigned *getSuperRegisters(unsigned RegNo) const { - return get(RegNo).SuperRegs; - } - - /// getName - Return the human-readable symbolic target-specific name for the - /// specified physical register. - const char *getName(unsigned RegNo) const { - return get(RegNo).Name; - } - /// getCostPerUse - Return the additional cost of using this register instead /// of other registers in its class. unsigned getCostPerUse(unsigned RegNo) const { - return get(RegNo).CostPerUse; + return InfoDesc[RegNo].CostPerUse; } - /// getNumRegs - Return the number of registers this target has (useful for - /// sizing arrays holding per register information) - unsigned getNumRegs() const { - return NumRegs; + /// isInAllocatableClass - Return true if the register is in the allocation + /// of any register class. + bool isInAllocatableClass(unsigned RegNo) const { + return InfoDesc[RegNo].inAllocatableClass; } /// getSubRegIndexName - Return the human-readable symbolic target-specific diff --git a/include/llvm/Target/TargetRegistry.h b/include/llvm/Target/TargetRegistry.h index a464822..2e21901 100644 --- a/include/llvm/Target/TargetRegistry.h +++ b/include/llvm/Target/TargetRegistry.h @@ -33,6 +33,7 @@ namespace llvm { class MCContext; class MCDisassembler; class MCInstPrinter; + class MCRegisterInfo; class MCStreamer; class TargetAsmBackend; class TargetAsmLexer; @@ -64,7 +65,9 @@ namespace llvm { typedef unsigned (*TripleMatchQualityFnTy)(const std::string &TT); typedef MCAsmInfo *(*AsmInfoCtorFnTy)(const Target &T, - StringRef TT); + StringRef TT); + typedef MCRegisterInfo *(*RegInfoCtorFnTy)(const Target &T, + StringRef TT); typedef TargetMachine *(*TargetMachineCtorTy)(const Target &T, const std::string &TT, const std::string &Features); @@ -120,8 +123,14 @@ namespace llvm { /// HasJIT - Whether this target supports the JIT. bool HasJIT; + /// AsmInfoCtorFn - Constructor function for this target's MCAsmInfo, if + /// registered. AsmInfoCtorFnTy AsmInfoCtorFn; + /// RegInfoCtorFn - Constructor function for this target's MCRegisterInfo, + /// if registered. + RegInfoCtorFnTy RegInfoCtorFn; + /// TargetMachineCtorFn - Construction function for this target's /// TargetMachine, if registered. TargetMachineCtorTy TargetMachineCtorFn; @@ -231,6 +240,19 @@ namespace llvm { return AsmInfoCtorFn(*this, Triple); } + /// createRegInfo - Create a MCRegisterInfo implementation for the specified + /// target triple. + /// + /// \arg Triple - This argument is used to determine the target machine + /// feature set; it should always be provided. Generally this should be + /// either the target triple from the module, or the target triple of the + /// host if that does not exist. + MCRegisterInfo *createRegInfo(StringRef Triple) const { + if (!RegInfoCtorFn) + return 0; + return RegInfoCtorFn(*this, Triple); + } + /// createTargetMachine - Create a target specific machine implementation /// for the specified \arg Triple. /// @@ -444,6 +466,21 @@ namespace llvm { T.AsmInfoCtorFn = Fn; } + /// RegisterRegInfo - Register a MCRegisterInfo implementation for the + /// given target. + /// + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. + /// + /// @param T - The target being registered. + /// @param Fn - A function to construct a MCRegisterInfo for the target. + static void RegisterRegInfo(Target &T, Target::RegInfoCtorFnTy Fn) { + // Ignore duplicate registration. + if (!T.RegInfoCtorFn) + T.RegInfoCtorFn = Fn; + } + /// RegisterTargetMachine - Register a TargetMachine implementation for the /// given target. /// diff --git a/lib/CodeGen/RegisterClassInfo.h b/lib/CodeGen/RegisterClassInfo.h index 6f7d9c9..d21fd67 100644 --- a/lib/CodeGen/RegisterClassInfo.h +++ b/lib/CodeGen/RegisterClassInfo.h @@ -112,7 +112,7 @@ public: /// register, so a register allocator needs to track its liveness and /// availability. bool isAllocatable(unsigned PhysReg) const { - return TRI->get(PhysReg).inAllocatableClass && !isReserved(PhysReg); + return TRI->isInAllocatableClass(PhysReg) && !isReserved(PhysReg); } }; } // end namespace llvm diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/lib/Target/ARM/ARMBaseRegisterInfo.cpp index 9dc51b8..0e74ac0 100644 --- a/lib/Target/ARM/ARMBaseRegisterInfo.cpp +++ b/lib/Target/ARM/ARMBaseRegisterInfo.cpp @@ -39,6 +39,8 @@ #include "llvm/ADT/BitVector.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/CommandLine.h" +#include "ARMGenRegisterDesc.inc" +#include "ARMGenRegisterInfo.inc" using namespace llvm; @@ -54,7 +56,8 @@ EnableBasePointer("arm-use-base-pointer", cl::Hidden, cl::init(true), ARMBaseRegisterInfo::ARMBaseRegisterInfo(const ARMBaseInstrInfo &tii, const ARMSubtarget &sti) - : ARMGenRegisterInfo(ARM::ADJCALLSTACKDOWN, ARM::ADJCALLSTACKUP), + : ARMGenRegisterInfo(ARMRegDesc, ARMRegInfoDesc, + ARM::ADJCALLSTACKDOWN, ARM::ADJCALLSTACKUP), TII(tii), STI(sti), FramePtr((STI.isTargetDarwin() || STI.isThumb()) ? ARM::R7 : ARM::R11), BasePtr(ARM::R6) { @@ -1287,5 +1290,3 @@ ARMBaseRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, MI.setDesc(TII.get(ARM::t2SUBri)); } } - -#include "ARMGenRegisterInfo.inc" diff --git a/lib/Target/ARM/CMakeLists.txt b/lib/Target/ARM/CMakeLists.txt index edc0054..6cb9689 100644 --- a/lib/Target/ARM/CMakeLists.txt +++ b/lib/Target/ARM/CMakeLists.txt @@ -1,8 +1,9 @@ set(LLVM_TARGET_DEFINITIONS ARM.td) -tablegen(ARMGenRegisterInfo.h.inc -gen-register-desc-header) tablegen(ARMGenRegisterNames.inc -gen-register-enums) -tablegen(ARMGenRegisterInfo.inc -gen-register-desc) +tablegen(ARMGenRegisterDesc.inc -gen-register-desc) +tablegen(ARMGenRegisterInfo.h.inc -gen-register-info-header) +tablegen(ARMGenRegisterInfo.inc -gen-register-info) tablegen(ARMGenInstrNames.inc -gen-instr-enums) tablegen(ARMGenInstrInfo.inc -gen-instr-desc) tablegen(ARMGenCodeEmitter.inc -gen-emitter) diff --git a/lib/Target/ARM/Makefile b/lib/Target/ARM/Makefile index 65a6494..0a42514 100644 --- a/lib/Target/ARM/Makefile +++ b/lib/Target/ARM/Makefile @@ -12,9 +12,10 @@ LIBRARYNAME = LLVMARMCodeGen TARGET = ARM # Make sure that tblgen is run, first thing. -BUILT_SOURCES = ARMGenRegisterInfo.h.inc ARMGenRegisterNames.inc \ - ARMGenRegisterInfo.inc ARMGenInstrNames.inc \ - ARMGenInstrInfo.inc ARMGenAsmWriter.inc ARMGenAsmMatcher.inc \ +BUILT_SOURCES = ARMGenRegisterNames.inc ARMGenRegisterDesc.inc \ + ARMGenRegisterInfo.h.inc ARMGenRegisterInfo.inc \ + ARMGenInstrNames.inc ARMGenInstrInfo.inc \ + ARMGenAsmWriter.inc ARMGenAsmMatcher.inc \ ARMGenDAGISel.inc ARMGenSubtarget.inc \ ARMGenCodeEmitter.inc ARMGenCallingConv.inc \ ARMGenDecoderTables.inc ARMGenEDInfo.inc \ diff --git a/lib/Target/Alpha/AlphaRegisterInfo.cpp b/lib/Target/Alpha/AlphaRegisterInfo.cpp index d6c3809..5ff846e 100644 --- a/lib/Target/Alpha/AlphaRegisterInfo.cpp +++ b/lib/Target/Alpha/AlphaRegisterInfo.cpp @@ -33,10 +33,13 @@ #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" #include +#include "AlphaGenRegisterDesc.inc" +#include "AlphaGenRegisterInfo.inc" using namespace llvm; AlphaRegisterInfo::AlphaRegisterInfo(const TargetInstrInfo &tii) - : AlphaGenRegisterInfo(Alpha::ADJUSTSTACKDOWN, Alpha::ADJUSTSTACKUP), + : AlphaGenRegisterInfo(AlphaRegDesc, AlphaRegInfoDesc, + Alpha::ADJUSTSTACKDOWN, Alpha::ADJUSTSTACKUP), TII(tii) { } @@ -204,10 +207,8 @@ int AlphaRegisterInfo::getLLVMRegNum(unsigned DwarfRegNum, bool isEH) const { return -1; } -#include "AlphaGenRegisterInfo.inc" - std::string AlphaRegisterInfo::getPrettyName(unsigned reg) { - std::string s(RegisterDescriptors[reg].Name); + std::string s(AlphaRegDesc[reg].Name); return s; } diff --git a/lib/Target/Alpha/CMakeLists.txt b/lib/Target/Alpha/CMakeLists.txt index 454262a..1834b06 100644 --- a/lib/Target/Alpha/CMakeLists.txt +++ b/lib/Target/Alpha/CMakeLists.txt @@ -1,8 +1,9 @@ set(LLVM_TARGET_DEFINITIONS Alpha.td) -tablegen(AlphaGenRegisterInfo.h.inc -gen-register-desc-header) tablegen(AlphaGenRegisterNames.inc -gen-register-enums) -tablegen(AlphaGenRegisterInfo.inc -gen-register-desc) +tablegen(AlphaGenRegisterDesc.inc -gen-register-desc) +tablegen(AlphaGenRegisterInfo.h.inc -gen-register-info-header) +tablegen(AlphaGenRegisterInfo.inc -gen-register-info) tablegen(AlphaGenInstrNames.inc -gen-instr-enums) tablegen(AlphaGenInstrInfo.inc -gen-instr-desc) tablegen(AlphaGenAsmWriter.inc -gen-asm-writer) diff --git a/lib/Target/Alpha/Makefile b/lib/Target/Alpha/Makefile index 9564be6..f029793 100644 --- a/lib/Target/Alpha/Makefile +++ b/lib/Target/Alpha/Makefile @@ -12,9 +12,9 @@ LIBRARYNAME = LLVMAlphaCodeGen TARGET = Alpha # Make sure that tblgen is run, first thing. -BUILT_SOURCES = AlphaGenRegisterInfo.h.inc AlphaGenRegisterNames.inc \ - AlphaGenRegisterInfo.inc AlphaGenInstrNames.inc \ - AlphaGenInstrInfo.inc \ +BUILT_SOURCES = AlphaGenRegisterNames.inc AlphaGenRegisterDesc.inc \ + AlphaGenRegisterInfo.h.inc AlphaGenRegisterInfo.inc \ + AlphaGenInstrNames.inc AlphaGenInstrInfo.inc \ AlphaGenAsmWriter.inc AlphaGenDAGISel.inc \ AlphaGenCallingConv.inc AlphaGenSubtarget.inc diff --git a/lib/Target/Blackfin/BlackfinRegisterInfo.cpp b/lib/Target/Blackfin/BlackfinRegisterInfo.cpp index 6ca460e..6377d8e 100644 --- a/lib/Target/Blackfin/BlackfinRegisterInfo.cpp +++ b/lib/Target/Blackfin/BlackfinRegisterInfo.cpp @@ -29,11 +29,14 @@ #include "llvm/Type.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" +#include "BlackfinGenRegisterDesc.inc" +#include "BlackfinGenRegisterInfo.inc" using namespace llvm; BlackfinRegisterInfo::BlackfinRegisterInfo(BlackfinSubtarget &st, const TargetInstrInfo &tii) - : BlackfinGenRegisterInfo(BF::ADJCALLSTACKDOWN, BF::ADJCALLSTACKUP), + : BlackfinGenRegisterInfo(BlackfinRegDesc, BlackfinRegInfoDesc, + BF::ADJCALLSTACKDOWN, BF::ADJCALLSTACKUP), Subtarget(st), TII(tii) {} @@ -356,6 +359,3 @@ int BlackfinRegisterInfo::getLLVMRegNum(unsigned DwarfRegNum, llvm_unreachable("What is the dwarf register number"); return -1; } - -#include "BlackfinGenRegisterInfo.inc" - diff --git a/lib/Target/Blackfin/CMakeLists.txt b/lib/Target/Blackfin/CMakeLists.txt index a47299f..10896c5 100644 --- a/lib/Target/Blackfin/CMakeLists.txt +++ b/lib/Target/Blackfin/CMakeLists.txt @@ -1,8 +1,9 @@ set(LLVM_TARGET_DEFINITIONS Blackfin.td) -tablegen(BlackfinGenRegisterInfo.h.inc -gen-register-desc-header) tablegen(BlackfinGenRegisterNames.inc -gen-register-enums) -tablegen(BlackfinGenRegisterInfo.inc -gen-register-desc) +tablegen(BlackfinGenRegisterDesc.inc -gen-register-desc) +tablegen(BlackfinGenRegisterInfo.h.inc -gen-register-info-header) +tablegen(BlackfinGenRegisterInfo.inc -gen-register-info) tablegen(BlackfinGenInstrNames.inc -gen-instr-enums) tablegen(BlackfinGenInstrInfo.inc -gen-instr-desc) tablegen(BlackfinGenAsmWriter.inc -gen-asm-writer) diff --git a/lib/Target/Blackfin/Makefile b/lib/Target/Blackfin/Makefile index 5eb8e9a..8ea1dfb 100644 --- a/lib/Target/Blackfin/Makefile +++ b/lib/Target/Blackfin/Makefile @@ -12,8 +12,9 @@ LIBRARYNAME = LLVMBlackfinCodeGen TARGET = Blackfin # Make sure that tblgen is run, first thing. -BUILT_SOURCES = BlackfinGenRegisterInfo.h.inc BlackfinGenRegisterNames.inc \ - BlackfinGenRegisterInfo.inc BlackfinGenInstrNames.inc \ +BUILT_SOURCES = BlackfinGenRegisterNames.inc BlackfinGenRegisterDesc.inc \ + BlackfinGenRegisterInfo.h.inc BlackfinGenRegisterInfo.inc \ + BlackfinGenInstrNames.inc \ BlackfinGenInstrInfo.inc BlackfinGenAsmWriter.inc \ BlackfinGenDAGISel.inc BlackfinGenSubtarget.inc \ BlackfinGenCallingConv.inc BlackfinGenIntrinsics.inc diff --git a/lib/Target/CellSPU/Makefile b/lib/Target/CellSPU/Makefile index 77c66be..de8a947 100644 --- a/lib/Target/CellSPU/Makefile +++ b/lib/Target/CellSPU/Makefile @@ -10,8 +10,9 @@ LEVEL = ../../.. LIBRARYNAME = LLVMCellSPUCodeGen TARGET = SPU -BUILT_SOURCES = SPUGenInstrNames.inc SPUGenRegisterNames.inc \ +BUILT_SOURCES = SPUGenInstrNames.inc \ SPUGenAsmWriter.inc SPUGenCodeEmitter.inc \ + SPUGenRegisterNames.inc SPUGenRegisterDesc.inc \ SPUGenRegisterInfo.h.inc SPUGenRegisterInfo.inc \ SPUGenInstrInfo.inc SPUGenDAGISel.inc \ SPUGenSubtarget.inc SPUGenCallingConv.inc diff --git a/lib/Target/CellSPU/SPURegisterInfo.cpp b/lib/Target/CellSPU/SPURegisterInfo.cpp index 623ae76..34f3f9b 100644 --- a/lib/Target/CellSPU/SPURegisterInfo.cpp +++ b/lib/Target/CellSPU/SPURegisterInfo.cpp @@ -42,6 +42,8 @@ #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" #include +#include "SPUGenRegisterDesc.inc" +#include "SPUGenRegisterInfo.inc" using namespace llvm; @@ -185,7 +187,8 @@ unsigned SPURegisterInfo::getRegisterNumbering(unsigned RegEnum) { SPURegisterInfo::SPURegisterInfo(const SPUSubtarget &subtarget, const TargetInstrInfo &tii) : - SPUGenRegisterInfo(SPU::ADJCALLSTACKDOWN, SPU::ADJCALLSTACKUP), + SPUGenRegisterInfo(SPURegDesc, SPURegInfoDesc, + SPU::ADJCALLSTACKDOWN, SPU::ADJCALLSTACKUP), Subtarget(subtarget), TII(tii) { @@ -371,5 +374,3 @@ SPURegisterInfo::findScratchRegister(MachineBasicBlock::iterator II, assert( Reg && "Register scavenger failed"); return Reg; } - -#include "SPUGenRegisterInfo.inc" diff --git a/lib/Target/MBlaze/CMakeLists.txt b/lib/Target/MBlaze/CMakeLists.txt index 004057a..009564e 100644 --- a/lib/Target/MBlaze/CMakeLists.txt +++ b/lib/Target/MBlaze/CMakeLists.txt @@ -1,8 +1,9 @@ set(LLVM_TARGET_DEFINITIONS MBlaze.td) -tablegen(MBlazeGenRegisterInfo.h.inc -gen-register-desc-header) tablegen(MBlazeGenRegisterNames.inc -gen-register-enums) -tablegen(MBlazeGenRegisterInfo.inc -gen-register-desc) +tablegen(MBlazeGenRegisterDesc.inc -gen-register-desc) +tablegen(MBlazeGenRegisterInfo.h.inc -gen-register-info-header) +tablegen(MBlazeGenRegisterInfo.inc -gen-register-info) tablegen(MBlazeGenInstrNames.inc -gen-instr-enums) tablegen(MBlazeGenInstrInfo.inc -gen-instr-desc) tablegen(MBlazeGenCodeEmitter.inc -gen-emitter) diff --git a/lib/Target/MBlaze/MBlazeRegisterInfo.cpp b/lib/Target/MBlaze/MBlazeRegisterInfo.cpp index 517279f..f52c2e1 100644 --- a/lib/Target/MBlaze/MBlazeRegisterInfo.cpp +++ b/lib/Target/MBlaze/MBlazeRegisterInfo.cpp @@ -36,12 +36,14 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" - +#include "MBlazeGenRegisterDesc.inc" +#include "MBlazeGenRegisterInfo.inc" using namespace llvm; MBlazeRegisterInfo:: MBlazeRegisterInfo(const MBlazeSubtarget &ST, const TargetInstrInfo &tii) - : MBlazeGenRegisterInfo(MBlaze::ADJCALLSTACKDOWN, MBlaze::ADJCALLSTACKUP), + : MBlazeGenRegisterInfo(MBlazeRegDesc, MBlazeRegInfoDesc, + MBlaze::ADJCALLSTACKDOWN, MBlaze::ADJCALLSTACKUP), Subtarget(ST), TII(tii) {} /// getRegisterNumbering - Given the enum value for some register, e.g. @@ -359,6 +361,3 @@ int MBlazeRegisterInfo::getDwarfRegNum(unsigned RegNo, bool isEH) const { int MBlazeRegisterInfo::getLLVMRegNum(unsigned DwarfRegNo, bool isEH) const { return MBlazeGenRegisterInfo::getLLVMRegNumFull(DwarfRegNo,0); } - -#include "MBlazeGenRegisterInfo.inc" - diff --git a/lib/Target/MBlaze/Makefile b/lib/Target/MBlaze/Makefile index e01c60b..81fd5f7 100644 --- a/lib/Target/MBlaze/Makefile +++ b/lib/Target/MBlaze/Makefile @@ -12,12 +12,13 @@ TARGET = MBlaze # Make sure that tblgen is run, first thing. BUILT_SOURCES = MBlazeGenRegisterInfo.h.inc MBlazeGenRegisterNames.inc \ - MBlazeGenRegisterInfo.inc MBlazeGenInstrNames.inc \ - MBlazeGenInstrInfo.inc MBlazeGenAsmWriter.inc \ - MBlazeGenDAGISel.inc MBlazeGenAsmMatcher.inc \ - MBlazeGenCodeEmitter.inc MBlazeGenCallingConv.inc \ - MBlazeGenSubtarget.inc MBlazeGenIntrinsics.inc \ - MBlazeGenEDInfo.inc + MBlazeGenRegisterInfo.inc MBlazeGenRegisterDesc.inc \ + MBlazeGenInstrNames.inc \ + MBlazeGenInstrInfo.inc MBlazeGenAsmWriter.inc \ + MBlazeGenDAGISel.inc MBlazeGenAsmMatcher.inc \ + MBlazeGenCodeEmitter.inc MBlazeGenCallingConv.inc \ + MBlazeGenSubtarget.inc MBlazeGenIntrinsics.inc \ + MBlazeGenEDInfo.inc DIRS = InstPrinter AsmParser Disassembler TargetInfo diff --git a/lib/Target/MSP430/CMakeLists.txt b/lib/Target/MSP430/CMakeLists.txt index 2c7cbb6..90752fa 100644 --- a/lib/Target/MSP430/CMakeLists.txt +++ b/lib/Target/MSP430/CMakeLists.txt @@ -1,8 +1,9 @@ set(LLVM_TARGET_DEFINITIONS MSP430.td) -tablegen(MSP430GenRegisterInfo.h.inc -gen-register-desc-header) tablegen(MSP430GenRegisterNames.inc -gen-register-enums) -tablegen(MSP430GenRegisterInfo.inc -gen-register-desc) +tablegen(MSP430GenRegisterDesc.inc -gen-register-desc) +tablegen(MSP430GenRegisterInfo.h.inc -gen-register-info-header) +tablegen(MSP430GenRegisterInfo.inc -gen-register-info) tablegen(MSP430GenInstrNames.inc -gen-instr-enums) tablegen(MSP430GenInstrInfo.inc -gen-instr-desc) tablegen(MSP430GenAsmWriter.inc -gen-asm-writer) diff --git a/lib/Target/MSP430/MSP430RegisterInfo.cpp b/lib/Target/MSP430/MSP430RegisterInfo.cpp index 53f4c2e..397b7b4 100644 --- a/lib/Target/MSP430/MSP430RegisterInfo.cpp +++ b/lib/Target/MSP430/MSP430RegisterInfo.cpp @@ -25,13 +25,16 @@ #include "llvm/Target/TargetOptions.h" #include "llvm/ADT/BitVector.h" #include "llvm/Support/ErrorHandling.h" +#include "MSP430GenRegisterDesc.inc" +#include "MSP430GenRegisterInfo.inc" using namespace llvm; // FIXME: Provide proper call frame setup / destroy opcodes. MSP430RegisterInfo::MSP430RegisterInfo(MSP430TargetMachine &tm, const TargetInstrInfo &tii) - : MSP430GenRegisterInfo(MSP430::ADJCALLSTACKDOWN, MSP430::ADJCALLSTACKUP), + : MSP430GenRegisterInfo(MSP430RegDesc, MSP430RegInfoDesc, + MSP430::ADJCALLSTACKDOWN, MSP430::ADJCALLSTACKUP), TM(tm), TII(tii) { StackAlign = TM.getFrameLowering()->getStackAlignment(); } @@ -250,5 +253,3 @@ int MSP430RegisterInfo::getLLVMRegNum(unsigned RegNum, bool isEH) const { llvm_unreachable("Not implemented yet!"); return 0; } - -#include "MSP430GenRegisterInfo.inc" diff --git a/lib/Target/MSP430/Makefile b/lib/Target/MSP430/Makefile index fa4e80b..8635646 100644 --- a/lib/Target/MSP430/Makefile +++ b/lib/Target/MSP430/Makefile @@ -13,7 +13,8 @@ TARGET = MSP430 # Make sure that tblgen is run, first thing. BUILT_SOURCES = MSP430GenRegisterInfo.h.inc MSP430GenRegisterNames.inc \ - MSP430GenRegisterInfo.inc MSP430GenInstrNames.inc \ + MSP430GenRegisterInfo.inc MSP430GenRegisterDesc.inc \ + MSP430GenInstrNames.inc \ MSP430GenInstrInfo.inc MSP430GenAsmWriter.inc \ MSP430GenDAGISel.inc MSP430GenCallingConv.inc \ MSP430GenSubtarget.inc diff --git a/lib/Target/Mips/CMakeLists.txt b/lib/Target/Mips/CMakeLists.txt index fd16516..f9d9536 100644 --- a/lib/Target/Mips/CMakeLists.txt +++ b/lib/Target/Mips/CMakeLists.txt @@ -1,8 +1,9 @@ set(LLVM_TARGET_DEFINITIONS Mips.td) -tablegen(MipsGenRegisterInfo.h.inc -gen-register-desc-header) tablegen(MipsGenRegisterNames.inc -gen-register-enums) -tablegen(MipsGenRegisterInfo.inc -gen-register-desc) +tablegen(MipsGenRegisterDesc.inc -gen-register-desc) +tablegen(MipsGenRegisterInfo.h.inc -gen-register-info-header) +tablegen(MipsGenRegisterInfo.inc -gen-register-info) tablegen(MipsGenInstrNames.inc -gen-instr-enums) tablegen(MipsGenInstrInfo.inc -gen-instr-desc) tablegen(MipsGenAsmWriter.inc -gen-asm-writer) diff --git a/lib/Target/Mips/Makefile b/lib/Target/Mips/Makefile index d16b066..d7eab61 100644 --- a/lib/Target/Mips/Makefile +++ b/lib/Target/Mips/Makefile @@ -13,7 +13,8 @@ TARGET = Mips # Make sure that tblgen is run, first thing. BUILT_SOURCES = MipsGenRegisterInfo.h.inc MipsGenRegisterNames.inc \ - MipsGenRegisterInfo.inc MipsGenInstrNames.inc \ + MipsGenRegisterInfo.inc MipsGenRegisterDesc.inc \ + MipsGenInstrNames.inc \ MipsGenInstrInfo.inc MipsGenAsmWriter.inc \ MipsGenDAGISel.inc MipsGenCallingConv.inc \ MipsGenSubtarget.inc diff --git a/lib/Target/Mips/MipsRegisterInfo.cpp b/lib/Target/Mips/MipsRegisterInfo.cpp index fa64f63..6fdcf45 100644 --- a/lib/Target/Mips/MipsRegisterInfo.cpp +++ b/lib/Target/Mips/MipsRegisterInfo.cpp @@ -35,12 +35,15 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" +#include "MipsGenRegisterDesc.inc" +#include "MipsGenRegisterInfo.inc" using namespace llvm; MipsRegisterInfo::MipsRegisterInfo(const MipsSubtarget &ST, const TargetInstrInfo &tii) - : MipsGenRegisterInfo(Mips::ADJCALLSTACKDOWN, Mips::ADJCALLSTACKUP), + : MipsGenRegisterInfo(MipsRegDesc, MipsRegInfoDesc, + Mips::ADJCALLSTACKDOWN, Mips::ADJCALLSTACKUP), Subtarget(ST), TII(tii) {} /// getRegisterNumbering - Given the enum value for some register, e.g. @@ -285,5 +288,3 @@ getDwarfRegNum(unsigned RegNum, bool isEH) const { int MipsRegisterInfo::getLLVMRegNum(unsigned DwarfRegNo, bool isEH) const { return MipsGenRegisterInfo::getLLVMRegNumFull(DwarfRegNo,0); } - -#include "MipsGenRegisterInfo.inc" diff --git a/lib/Target/PTX/CMakeLists.txt b/lib/Target/PTX/CMakeLists.txt index c4448d6..540af72 100644 --- a/lib/Target/PTX/CMakeLists.txt +++ b/lib/Target/PTX/CMakeLists.txt @@ -5,8 +5,9 @@ tablegen(PTXGenCallingConv.inc -gen-callingconv) tablegen(PTXGenDAGISel.inc -gen-dag-isel) tablegen(PTXGenInstrInfo.inc -gen-instr-desc) tablegen(PTXGenInstrNames.inc -gen-instr-enums) -tablegen(PTXGenRegisterInfo.inc -gen-register-desc) -tablegen(PTXGenRegisterInfo.h.inc -gen-register-desc-header) +tablegen(PTXGenRegisterDesc.inc -gen-register-desc) +tablegen(PTXGenRegisterInfo.inc -gen-register-info) +tablegen(PTXGenRegisterInfo.h.inc -gen-register-info-header) tablegen(PTXGenRegisterNames.inc -gen-register-enums) tablegen(PTXGenSubtarget.inc -gen-subtarget) diff --git a/lib/Target/PTX/Makefile b/lib/Target/PTX/Makefile index 844480f..1e471de 100644 --- a/lib/Target/PTX/Makefile +++ b/lib/Target/PTX/Makefile @@ -17,6 +17,7 @@ BUILT_SOURCES = PTXGenAsmWriter.inc \ PTXGenDAGISel.inc \ PTXGenInstrInfo.inc \ PTXGenInstrNames.inc \ + PTXGenRegisterDesc.inc \ PTXGenRegisterInfo.inc \ PTXGenRegisterInfo.h.inc \ PTXGenRegisterNames.inc \ diff --git a/lib/Target/PTX/PTXRegisterInfo.cpp b/lib/Target/PTX/PTXRegisterInfo.cpp index b7c7ee5..5673f96 100644 --- a/lib/Target/PTX/PTXRegisterInfo.cpp +++ b/lib/Target/PTX/PTXRegisterInfo.cpp @@ -19,9 +19,15 @@ using namespace llvm; +#include "PTXGenRegisterDesc.inc" #include "PTXGenRegisterInfo.inc" +PTXRegisterInfo::PTXRegisterInfo(PTXTargetMachine &TM, + const TargetInstrInfo &TII) + : PTXGenRegisterInfo(PTXRegDesc, PTXRegInfoDesc) { +} + void PTXRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, RegScavenger *RS) const { diff --git a/lib/Target/PTX/PTXRegisterInfo.h b/lib/Target/PTX/PTXRegisterInfo.h index 223e965..67e8a1b 100644 --- a/lib/Target/PTX/PTXRegisterInfo.h +++ b/lib/Target/PTX/PTXRegisterInfo.h @@ -25,7 +25,7 @@ class MachineFunction; struct PTXRegisterInfo : public PTXGenRegisterInfo { PTXRegisterInfo(PTXTargetMachine &TM, - const TargetInstrInfo &TII) {} + const TargetInstrInfo &TII); virtual const unsigned *getCalleeSavedRegs(const MachineFunction *MF = 0) const { diff --git a/lib/Target/PowerPC/CMakeLists.txt b/lib/Target/PowerPC/CMakeLists.txt index f282579..99caa99 100644 --- a/lib/Target/PowerPC/CMakeLists.txt +++ b/lib/Target/PowerPC/CMakeLists.txt @@ -5,8 +5,9 @@ tablegen(PPCGenRegisterNames.inc -gen-register-enums) tablegen(PPCGenAsmWriter.inc -gen-asm-writer) tablegen(PPCGenCodeEmitter.inc -gen-emitter) tablegen(PPCGenMCCodeEmitter.inc -gen-emitter -mc-emitter) -tablegen(PPCGenRegisterInfo.h.inc -gen-register-desc-header) -tablegen(PPCGenRegisterInfo.inc -gen-register-desc) +tablegen(PPCGenRegisterDesc.inc -gen-register-desc) +tablegen(PPCGenRegisterInfo.h.inc -gen-register-info-header) +tablegen(PPCGenRegisterInfo.inc -gen-register-info) tablegen(PPCGenInstrInfo.inc -gen-instr-desc) tablegen(PPCGenDAGISel.inc -gen-dag-isel) tablegen(PPCGenCallingConv.inc -gen-callingconv) diff --git a/lib/Target/PowerPC/Makefile b/lib/Target/PowerPC/Makefile index 030defe..3d01792 100644 --- a/lib/Target/PowerPC/Makefile +++ b/lib/Target/PowerPC/Makefile @@ -14,6 +14,7 @@ TARGET = PPC # Make sure that tblgen is run, first thing. BUILT_SOURCES = PPCGenInstrNames.inc PPCGenRegisterNames.inc \ PPCGenAsmWriter.inc PPCGenCodeEmitter.inc \ + PPCGenRegisterDesc.inc \ PPCGenRegisterInfo.h.inc PPCGenRegisterInfo.inc \ PPCGenInstrInfo.inc PPCGenDAGISel.inc \ PPCGenSubtarget.inc PPCGenCallingConv.inc \ diff --git a/lib/Target/PowerPC/PPCRegisterInfo.cpp b/lib/Target/PowerPC/PPCRegisterInfo.cpp index fd62a88..3950517 100644 --- a/lib/Target/PowerPC/PPCRegisterInfo.cpp +++ b/lib/Target/PowerPC/PPCRegisterInfo.cpp @@ -43,6 +43,8 @@ #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" #include +#include "PPCGenRegisterDesc.inc" +#include "PPCGenRegisterInfo.inc" // FIXME (64-bit): Eventually enable by default. namespace llvm { @@ -110,7 +112,8 @@ unsigned PPCRegisterInfo::getRegisterNumbering(unsigned RegEnum) { PPCRegisterInfo::PPCRegisterInfo(const PPCSubtarget &ST, const TargetInstrInfo &tii) - : PPCGenRegisterInfo(PPC::ADJCALLSTACKDOWN, PPC::ADJCALLSTACKUP), + : PPCGenRegisterInfo(PPCRegDesc, PPCRegInfoDesc, + PPC::ADJCALLSTACKDOWN, PPC::ADJCALLSTACKUP), Subtarget(ST), TII(tii) { ImmToIdxMap[PPC::LD] = PPC::LDX; ImmToIdxMap[PPC::STD] = PPC::STDX; ImmToIdxMap[PPC::LBZ] = PPC::LBZX; ImmToIdxMap[PPC::STB] = PPC::STBX; @@ -710,5 +713,3 @@ int PPCRegisterInfo::getLLVMRegNum(unsigned RegNum, bool isEH) const { return PPCGenRegisterInfo::getLLVMRegNumFull(RegNum, Flavour); } - -#include "PPCGenRegisterInfo.inc" diff --git a/lib/Target/Sparc/CMakeLists.txt b/lib/Target/Sparc/CMakeLists.txt index 6839234..243e889 100644 --- a/lib/Target/Sparc/CMakeLists.txt +++ b/lib/Target/Sparc/CMakeLists.txt @@ -1,8 +1,9 @@ set(LLVM_TARGET_DEFINITIONS Sparc.td) -tablegen(SparcGenRegisterInfo.h.inc -gen-register-desc-header) tablegen(SparcGenRegisterNames.inc -gen-register-enums) -tablegen(SparcGenRegisterInfo.inc -gen-register-desc) +tablegen(SparcGenRegisterDesc.inc -gen-register-desc) +tablegen(SparcGenRegisterInfo.h.inc -gen-register-info-header) +tablegen(SparcGenRegisterInfo.inc -gen-register-info) tablegen(SparcGenInstrNames.inc -gen-instr-enums) tablegen(SparcGenInstrInfo.inc -gen-instr-desc) tablegen(SparcGenAsmWriter.inc -gen-asm-writer) diff --git a/lib/Target/Sparc/Makefile b/lib/Target/Sparc/Makefile index 27942c5..af7d9da 100644 --- a/lib/Target/Sparc/Makefile +++ b/lib/Target/Sparc/Makefile @@ -13,7 +13,8 @@ TARGET = Sparc # Make sure that tblgen is run, first thing. BUILT_SOURCES = SparcGenRegisterInfo.h.inc SparcGenRegisterNames.inc \ - SparcGenRegisterInfo.inc SparcGenInstrNames.inc \ + SparcGenRegisterInfo.inc SparcGenRegisterDesc.inc \ + SparcGenInstrNames.inc \ SparcGenInstrInfo.inc SparcGenAsmWriter.inc \ SparcGenDAGISel.inc SparcGenSubtarget.inc SparcGenCallingConv.inc diff --git a/lib/Target/Sparc/SparcRegisterInfo.cpp b/lib/Target/Sparc/SparcRegisterInfo.cpp index 9fcf028..c63f52e 100644 --- a/lib/Target/Sparc/SparcRegisterInfo.cpp +++ b/lib/Target/Sparc/SparcRegisterInfo.cpp @@ -23,11 +23,14 @@ #include "llvm/Type.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" +#include "SparcGenRegisterDesc.inc" +#include "SparcGenRegisterInfo.inc" using namespace llvm; SparcRegisterInfo::SparcRegisterInfo(SparcSubtarget &st, const TargetInstrInfo &tii) - : SparcGenRegisterInfo(SP::ADJCALLSTACKDOWN, SP::ADJCALLSTACKUP), + : SparcGenRegisterInfo(SparcRegDesc, SparcRegInfoDesc, + SP::ADJCALLSTACKDOWN, SP::ADJCALLSTACKUP), Subtarget(st), TII(tii) { } @@ -135,6 +138,3 @@ int SparcRegisterInfo::getDwarfRegNum(unsigned RegNum, bool isEH) const { int SparcRegisterInfo::getLLVMRegNum(unsigned DwarfRegNo, bool isEH) const { return SparcGenRegisterInfo::getLLVMRegNumFull(DwarfRegNo,0); } - -#include "SparcGenRegisterInfo.inc" - diff --git a/lib/Target/SystemZ/CMakeLists.txt b/lib/Target/SystemZ/CMakeLists.txt index 1f5d355..3e06109 100644 --- a/lib/Target/SystemZ/CMakeLists.txt +++ b/lib/Target/SystemZ/CMakeLists.txt @@ -1,8 +1,9 @@ set(LLVM_TARGET_DEFINITIONS SystemZ.td) -tablegen(SystemZGenRegisterInfo.h.inc -gen-register-desc-header) tablegen(SystemZGenRegisterNames.inc -gen-register-enums) -tablegen(SystemZGenRegisterInfo.inc -gen-register-desc) +tablegen(SystemZGenRegisterDesc.inc -gen-register-desc) +tablegen(SystemZGenRegisterInfo.h.inc -gen-register-info-header) +tablegen(SystemZGenRegisterInfo.inc -gen-register-info) tablegen(SystemZGenInstrNames.inc -gen-instr-enums) tablegen(SystemZGenInstrInfo.inc -gen-instr-desc) tablegen(SystemZGenAsmWriter.inc -gen-asm-writer) diff --git a/lib/Target/SystemZ/Makefile b/lib/Target/SystemZ/Makefile index 6930e14..2481715 100644 --- a/lib/Target/SystemZ/Makefile +++ b/lib/Target/SystemZ/Makefile @@ -13,7 +13,8 @@ TARGET = SystemZ # Make sure that tblgen is run, first thing. BUILT_SOURCES = SystemZGenRegisterInfo.h.inc SystemZGenRegisterNames.inc \ - SystemZGenRegisterInfo.inc SystemZGenInstrNames.inc \ + SystemZGenRegisterInfo.inc SystemZGenRegisterDesc.inc \ + SystemZGenInstrNames.inc \ SystemZGenInstrInfo.inc SystemZGenAsmWriter.inc \ SystemZGenDAGISel.inc SystemZGenSubtarget.inc SystemZGenCallingConv.inc diff --git a/lib/Target/SystemZ/SystemZRegisterInfo.cpp b/lib/Target/SystemZ/SystemZRegisterInfo.cpp index d5c165f..a587e1c 100644 --- a/lib/Target/SystemZ/SystemZRegisterInfo.cpp +++ b/lib/Target/SystemZ/SystemZRegisterInfo.cpp @@ -25,11 +25,14 @@ #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include "llvm/ADT/BitVector.h" +#include "SystemZGenRegisterDesc.inc" +#include "SystemZGenRegisterInfo.inc" using namespace llvm; SystemZRegisterInfo::SystemZRegisterInfo(SystemZTargetMachine &tm, const SystemZInstrInfo &tii) - : SystemZGenRegisterInfo(SystemZ::ADJCALLSTACKUP, SystemZ::ADJCALLSTACKDOWN), + : SystemZGenRegisterInfo(SystemZRegDesc, SystemZRegInfoDesc, + SystemZ::ADJCALLSTACKUP, SystemZ::ADJCALLSTACKDOWN), TM(tm), TII(tii) { } @@ -153,6 +156,3 @@ int SystemZRegisterInfo::getLLVMRegNum(unsigned DwarfRegNo, bool isEH) const { assert(0 && "What is the dwarf register number"); return -1; } - - -#include "SystemZGenRegisterInfo.inc" diff --git a/lib/Target/TargetRegisterInfo.cpp b/lib/Target/TargetRegisterInfo.cpp index bae3343..d01130a 100644 --- a/lib/Target/TargetRegisterInfo.cpp +++ b/lib/Target/TargetRegisterInfo.cpp @@ -20,15 +20,12 @@ using namespace llvm; -TargetRegisterInfo::TargetRegisterInfo(const TargetRegisterDesc *D, unsigned NR, +TargetRegisterInfo::TargetRegisterInfo(const TargetRegisterInfoDesc *ID, regclass_iterator RCB, regclass_iterator RCE, const char *const *subregindexnames, int CFSO, int CFDO) - : Desc(D), SubRegIndexNames(subregindexnames), NumRegs(NR), + : InfoDesc(ID), SubRegIndexNames(subregindexnames), RegClassBegin(RCB), RegClassEnd(RCE) { - assert(isPhysicalRegister(NumRegs) && - "Target has too many physical registers!"); - CallFrameSetupOpcode = CFSO; CallFrameDestroyOpcode = CFDO; } @@ -86,7 +83,7 @@ static void getAllocatableSetForRC(const MachineFunction &MF, BitVector TargetRegisterInfo::getAllocatableSet(const MachineFunction &MF, const TargetRegisterClass *RC) const { - BitVector Allocatable(NumRegs); + BitVector Allocatable(getNumRegs()); if (RC) { getAllocatableSetForRC(MF, RC, Allocatable); } else { diff --git a/lib/Target/X86/CMakeLists.txt b/lib/Target/X86/CMakeLists.txt index b5fa94f..5e0c84f 100644 --- a/lib/Target/X86/CMakeLists.txt +++ b/lib/Target/X86/CMakeLists.txt @@ -1,8 +1,9 @@ set(LLVM_TARGET_DEFINITIONS X86.td) -tablegen(X86GenRegisterInfo.h.inc -gen-register-desc-header) tablegen(X86GenRegisterNames.inc -gen-register-enums) -tablegen(X86GenRegisterInfo.inc -gen-register-desc) +tablegen(X86GenRegisterDesc.inc -gen-register-desc) +tablegen(X86GenRegisterInfo.h.inc -gen-register-info-header) +tablegen(X86GenRegisterInfo.inc -gen-register-info) tablegen(X86GenDisassemblerTables.inc -gen-disassembler) tablegen(X86GenInstrNames.inc -gen-instr-enums) tablegen(X86GenInstrInfo.inc -gen-instr-desc) diff --git a/lib/Target/X86/Makefile b/lib/Target/X86/Makefile index 12fb090..9cd17ee 100644 --- a/lib/Target/X86/Makefile +++ b/lib/Target/X86/Makefile @@ -12,14 +12,15 @@ LIBRARYNAME = LLVMX86CodeGen TARGET = X86 # Make sure that tblgen is run, first thing. -BUILT_SOURCES = X86GenRegisterInfo.h.inc X86GenRegisterNames.inc \ - X86GenRegisterInfo.inc X86GenInstrNames.inc \ - X86GenInstrInfo.inc X86GenAsmWriter.inc X86GenAsmMatcher.inc \ +BUILT_SOURCES = X86GenRegisterNames.inc X86GenRegisterDesc.inc \ + X86GenRegisterInfo.h.inc X86GenRegisterInfo.inc \ + X86GenInstrNames.inc X86GenInstrInfo.inc \ + X86GenAsmWriter.inc X86GenAsmMatcher.inc \ X86GenAsmWriter1.inc X86GenDAGISel.inc \ X86GenDisassemblerTables.inc X86GenFastISel.inc \ X86GenCallingConv.inc X86GenSubtarget.inc \ X86GenEDInfo.inc -DIRS = InstPrinter AsmParser Disassembler TargetInfo Utils +DIRS = InstPrinter AsmParser Disassembler TargetInfo TargetDesc Utils include $(LEVEL)/Makefile.common diff --git a/lib/Target/X86/TargetDesc/Makefile b/lib/Target/X86/TargetDesc/Makefile new file mode 100644 index 0000000..b19774e --- /dev/null +++ b/lib/Target/X86/TargetDesc/Makefile @@ -0,0 +1,16 @@ +##===- lib/Target/X86/TargetDesc/Makefile ------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../../.. +LIBRARYNAME = LLVMX86Desc + +# Hack: we need to include 'main' target directory to grab private headers +CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common diff --git a/lib/Target/X86/TargetDesc/X86TargetDesc.cpp b/lib/Target/X86/TargetDesc/X86TargetDesc.cpp new file mode 100644 index 0000000..cf03d48 --- /dev/null +++ b/lib/Target/X86/TargetDesc/X86TargetDesc.cpp @@ -0,0 +1,23 @@ +//===-- X86TargetDesc.cpp - X86 Target Descriptions -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides X86 specific target descriptions. +// +//===----------------------------------------------------------------------===// + +#include "X86TargetDesc.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "X86GenRegisterDesc.inc" +using namespace llvm; + +MCRegisterInfo *createX86MCRegisterInfo() { + MCRegisterInfo *X = new MCRegisterInfo(); + InitX86MCRegisterInfo(X); + return X; +} diff --git a/lib/Target/X86/TargetDesc/X86TargetDesc.h b/lib/Target/X86/TargetDesc/X86TargetDesc.h new file mode 100644 index 0000000..d08aec7 --- /dev/null +++ b/lib/Target/X86/TargetDesc/X86TargetDesc.h @@ -0,0 +1,17 @@ +//===-- X86TargetDesc.h - X86 Target Descriptions ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides X86 specific target descriptions. +// +//===----------------------------------------------------------------------===// + +// Defines symbolic names for X86 registers. This defines a mapping from +// register name to register number. +// +#include "X86GenRegisterNames.inc" diff --git a/lib/Target/X86/X86.h b/lib/Target/X86/X86.h index 0ca4366..ec78d48 100644 --- a/lib/Target/X86/X86.h +++ b/lib/Target/X86/X86.h @@ -88,10 +88,7 @@ extern Target TheX86_32Target, TheX86_64Target; } // End llvm namespace -// Defines symbolic names for X86 registers. This defines a mapping from -// register name to register number. -// -#include "X86GenRegisterNames.inc" +#include "TargetDesc/X86TargetDesc.h" // Defines symbolic names for the X86 instructions. // diff --git a/lib/Target/X86/X86RegisterInfo.cpp b/lib/Target/X86/X86RegisterInfo.cpp index fa3e3f8..c67da21 100644 --- a/lib/Target/X86/X86RegisterInfo.cpp +++ b/lib/Target/X86/X86RegisterInfo.cpp @@ -39,6 +39,8 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/CommandLine.h" +#include "X86GenRegisterDesc.inc" +#include "X86GenRegisterInfo.inc" using namespace llvm; cl::opt @@ -49,7 +51,8 @@ ForceStackAlign("force-align-stack", X86RegisterInfo::X86RegisterInfo(X86TargetMachine &tm, const TargetInstrInfo &tii) - : X86GenRegisterInfo(tm.getSubtarget().is64Bit() ? + : X86GenRegisterInfo(X86RegDesc, X86RegInfoDesc, + tm.getSubtarget().is64Bit() ? X86::ADJCALLSTACKDOWN64 : X86::ADJCALLSTACKDOWN32, tm.getSubtarget().is64Bit() ? @@ -918,8 +921,6 @@ unsigned getX86SubSuperRegister(unsigned Reg, EVT VT, bool High) { } } -#include "X86GenRegisterInfo.inc" - namespace { struct MSAH : public MachineFunctionPass { static char ID; diff --git a/lib/Target/XCore/CMakeLists.txt b/lib/Target/XCore/CMakeLists.txt index 9093de6..1ed1538 100644 --- a/lib/Target/XCore/CMakeLists.txt +++ b/lib/Target/XCore/CMakeLists.txt @@ -1,8 +1,8 @@ set(LLVM_TARGET_DEFINITIONS XCore.td) -tablegen(XCoreGenRegisterInfo.h.inc -gen-register-desc-header) -tablegen(XCoreGenRegisterNames.inc -gen-register-enums) -tablegen(XCoreGenRegisterInfo.inc -gen-register-desc) +tablegen(XCoreGenRegisterDesc.inc -gen-register-desc) +tablegen(XCoreGenRegisterInfo.h.inc -gen-register-info-header) +tablegen(XCoreGenRegisterInfo.inc -gen-register-info) tablegen(XCoreGenInstrNames.inc -gen-instr-enums) tablegen(XCoreGenInstrInfo.inc -gen-instr-desc) tablegen(XCoreGenAsmWriter.inc -gen-asm-writer) diff --git a/lib/Target/XCore/Makefile b/lib/Target/XCore/Makefile index 6c1ef88..f67ef51 100644 --- a/lib/Target/XCore/Makefile +++ b/lib/Target/XCore/Makefile @@ -13,7 +13,8 @@ TARGET = XCore # Make sure that tblgen is run, first thing. BUILT_SOURCES = XCoreGenRegisterInfo.h.inc XCoreGenRegisterNames.inc \ - XCoreGenRegisterInfo.inc XCoreGenInstrNames.inc \ + XCoreGenRegisterInfo.inc XCoreGenRegisterDesc.inc \ + XCoreGenInstrNames.inc \ XCoreGenInstrInfo.inc XCoreGenAsmWriter.inc \ XCoreGenDAGISel.inc XCoreGenCallingConv.inc \ XCoreGenSubtarget.inc diff --git a/lib/Target/XCore/XCoreRegisterInfo.cpp b/lib/Target/XCore/XCoreRegisterInfo.cpp index 46c9e57..966e33b 100644 --- a/lib/Target/XCore/XCoreRegisterInfo.cpp +++ b/lib/Target/XCore/XCoreRegisterInfo.cpp @@ -32,11 +32,13 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" - +#include "XCoreGenRegisterDesc.inc" +#include "XCoreGenRegisterInfo.inc" using namespace llvm; XCoreRegisterInfo::XCoreRegisterInfo(const TargetInstrInfo &tii) - : XCoreGenRegisterInfo(XCore::ADJCALLSTACKDOWN, XCore::ADJCALLSTACKUP), + : XCoreGenRegisterInfo(XCoreRegDesc, XCoreRegInfoDesc, + XCore::ADJCALLSTACKDOWN, XCore::ADJCALLSTACKUP), TII(tii) { } @@ -328,6 +330,3 @@ unsigned XCoreRegisterInfo::getFrameRegister(const MachineFunction &MF) const { unsigned XCoreRegisterInfo::getRARegister() const { return XCore::LR; } - -#include "XCoreGenRegisterInfo.inc" - diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp index 991f34c..997f1c0 100644 --- a/utils/TableGen/RegisterInfoEmitter.cpp +++ b/utils/TableGen/RegisterInfoEmitter.cpp @@ -79,7 +79,8 @@ void RegisterInfoEmitter::runHeader(raw_ostream &OS) { OS << "struct " << ClassName << " : public TargetRegisterInfo {\n" << " explicit " << ClassName - << "(int CallFrameSetupOpcode = -1, int CallFrameDestroyOpcode = -1);\n" + << "(const TargetRegisterDesc *D, const TargetRegisterInfoDesc *ID, " + << "int CallFrameSetupOpcode = -1, int CallFrameDestroyOpcode = -1);\n" << " virtual int getDwarfRegNumFull(unsigned RegNum, " << "unsigned Flavour) const;\n" << " virtual int getLLVMRegNumFull(unsigned DwarfRegNum, " @@ -140,8 +141,6 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { CodeGenTarget Target(Records); CodeGenRegBank &RegBank = Target.getRegBank(); RegBank.computeDerivedInfo(); - std::map Overlaps; - RegBank.computeOverlaps(Overlaps); EmitSourceFileHeader("Register Information Source Fragment", OS); @@ -407,78 +406,22 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { << "RegClass,\n"; OS << " };\n"; - typedef std::map, LessRecord> DwarfRegNumsMapTy; - DwarfRegNumsMapTy DwarfRegNums; - const std::vector &Regs = RegBank.getRegisters(); - - // Emit an overlap list for all registers. - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - const CodeGenRegister *Reg = Regs[i]; - const CodeGenRegister::Set &O = Overlaps[Reg]; - // Move Reg to the front so TRI::getAliasSet can share the list. - OS << " const unsigned " << Reg->getName() << "_Overlaps[] = { " - << getQualifiedName(Reg->TheDef) << ", "; - for (CodeGenRegister::Set::const_iterator I = O.begin(), E = O.end(); - I != E; ++I) - if (*I != Reg) - OS << getQualifiedName((*I)->TheDef) << ", "; - OS << "0 };\n"; - } - - // Emit the empty sub-registers list - OS << " const unsigned Empty_SubRegsSet[] = { 0 };\n"; - // Loop over all of the registers which have sub-registers, emitting the - // sub-registers list to memory. - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - const CodeGenRegister &Reg = *Regs[i]; - if (Reg.getSubRegs().empty()) - continue; - // getSubRegs() orders by SubRegIndex. We want a topological order. - SetVector SR; - Reg.addSubRegsPreOrder(SR); - OS << " const unsigned " << Reg.getName() << "_SubRegsSet[] = { "; - for (unsigned j = 0, je = SR.size(); j != je; ++j) - OS << getQualifiedName(SR[j]->TheDef) << ", "; - OS << "0 };\n"; - } + // Emit extra information about registers. + OS << "\n static const TargetRegisterInfoDesc " + << Target.getName() << "RegInfoDesc[] = " + << "{ // Extra Descriptors\n"; + OS << " { 0, 0 },\n"; - // Emit the empty super-registers list - OS << " const unsigned Empty_SuperRegsSet[] = { 0 };\n"; - // Loop over all of the registers which have super-registers, emitting the - // super-registers list to memory. - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - const CodeGenRegister &Reg = *Regs[i]; - const CodeGenRegister::SuperRegList &SR = Reg.getSuperRegs(); - if (SR.empty()) - continue; - OS << " const unsigned " << Reg.getName() << "_SuperRegsSet[] = { "; - for (unsigned j = 0, je = SR.size(); j != je; ++j) - OS << getQualifiedName(SR[j]->TheDef) << ", "; - OS << "0 };\n"; - } - - OS<<"\n const TargetRegisterDesc RegisterDescriptors[] = { // Descriptors\n"; - OS << " { \"NOREG\",\t0,\t0,\t0,\t0,\t0 },\n"; - - // Now that register alias and sub-registers sets have been emitted, emit the - // register descriptors now. + const std::vector &Regs = RegBank.getRegisters(); for (unsigned i = 0, e = Regs.size(); i != e; ++i) { const CodeGenRegister &Reg = *Regs[i]; - OS << " { \""; - OS << Reg.getName() << "\",\t" << Reg.getName() << "_Overlaps,\t"; - if (!Reg.getSubRegs().empty()) - OS << Reg.getName() << "_SubRegsSet,\t"; - else - OS << "Empty_SubRegsSet,\t"; - if (!Reg.getSuperRegs().empty()) - OS << Reg.getName() << "_SuperRegsSet,\t"; - else - OS << "Empty_SuperRegsSet,\t"; - OS << Reg.CostPerUse << ",\t" + OS << " { "; + OS << Reg.CostPerUse << ", " << int(AllocatableRegs.count(Reg.TheDef)) << " },\n"; } OS << " };\n"; // End of register descriptors... + // Calculate the mapping of subregister+index pairs to physical registers. // This will also create further anonymous indexes. unsigned NamedIndices = RegBank.getNumNamedIndices(); @@ -575,14 +518,18 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { // Emit the constructor of the class... OS << ClassName << "::" << ClassName - << "(int CallFrameSetupOpcode, int CallFrameDestroyOpcode)\n" - << " : TargetRegisterInfo(RegisterDescriptors, " << Regs.size()+1 + << "(const TargetRegisterDesc *D, const TargetRegisterInfoDesc *ID, " + << "int CallFrameSetupOpcode, int CallFrameDestroyOpcode)\n" + << " : TargetRegisterInfo(ID" << ", RegisterClasses, RegisterClasses+" << RegisterClasses.size() <<",\n" << " SubRegIndexTable,\n" << " CallFrameSetupOpcode, CallFrameDestroyOpcode) {\n" + << " InitMCRegisterInfo(D, " << Regs.size()+1 << ");\n" << "}\n\n"; // Collect all information about dwarf register numbers + typedef std::map, LessRecord> DwarfRegNumsMapTy; + DwarfRegNumsMapTy DwarfRegNums; // First, just pull all provided information to the map unsigned maxLength = 0; @@ -671,3 +618,101 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { OS << "} // End llvm namespace \n"; } + +void RegisterInfoEmitter::runDesc(raw_ostream &OS) { + CodeGenTarget Target(Records); + CodeGenRegBank &RegBank = Target.getRegBank(); + RegBank.computeDerivedInfo(); + std::map Overlaps; + RegBank.computeOverlaps(Overlaps); + + OS << "namespace llvm {\n\n"; + + const std::string &TargetName = Target.getName(); + std::string ClassName = TargetName + "GenMCRegisterInfo"; + OS << "struct " << ClassName << " : public MCRegisterInfo {\n" + << " explicit " << ClassName << "(const TargetRegisterDesc *D);\n"; + OS << "};\n"; + + OS << "\nnamespace {\n"; + + const std::vector &Regs = RegBank.getRegisters(); + + // Emit an overlap list for all registers. + for (unsigned i = 0, e = Regs.size(); i != e; ++i) { + const CodeGenRegister *Reg = Regs[i]; + const CodeGenRegister::Set &O = Overlaps[Reg]; + // Move Reg to the front so TRI::getAliasSet can share the list. + OS << " const unsigned " << Reg->getName() << "_Overlaps[] = { " + << getQualifiedName(Reg->TheDef) << ", "; + for (CodeGenRegister::Set::const_iterator I = O.begin(), E = O.end(); + I != E; ++I) + if (*I != Reg) + OS << getQualifiedName((*I)->TheDef) << ", "; + OS << "0 };\n"; + } + + // Emit the empty sub-registers list + OS << " const unsigned Empty_SubRegsSet[] = { 0 };\n"; + // Loop over all of the registers which have sub-registers, emitting the + // sub-registers list to memory. + for (unsigned i = 0, e = Regs.size(); i != e; ++i) { + const CodeGenRegister &Reg = *Regs[i]; + if (Reg.getSubRegs().empty()) + continue; + // getSubRegs() orders by SubRegIndex. We want a topological order. + SetVector SR; + Reg.addSubRegsPreOrder(SR); + OS << " const unsigned " << Reg.getName() << "_SubRegsSet[] = { "; + for (unsigned j = 0, je = SR.size(); j != je; ++j) + OS << getQualifiedName(SR[j]->TheDef) << ", "; + OS << "0 };\n"; + } + + // Emit the empty super-registers list + OS << " const unsigned Empty_SuperRegsSet[] = { 0 };\n"; + // Loop over all of the registers which have super-registers, emitting the + // super-registers list to memory. + for (unsigned i = 0, e = Regs.size(); i != e; ++i) { + const CodeGenRegister &Reg = *Regs[i]; + const CodeGenRegister::SuperRegList &SR = Reg.getSuperRegs(); + if (SR.empty()) + continue; + OS << " const unsigned " << Reg.getName() << "_SuperRegsSet[] = { "; + for (unsigned j = 0, je = SR.size(); j != je; ++j) + OS << getQualifiedName(SR[j]->TheDef) << ", "; + OS << "0 };\n"; + } + + OS << "\n const TargetRegisterDesc " << TargetName + << "RegDesc[] = { // Descriptors\n"; + OS << " { \"NOREG\",\t0,\t0,\t0 },\n"; + + // Now that register alias and sub-registers sets have been emitted, emit the + // register descriptors now. + for (unsigned i = 0, e = Regs.size(); i != e; ++i) { + const CodeGenRegister &Reg = *Regs[i]; + OS << " { \""; + OS << Reg.getName() << "\",\t" << Reg.getName() << "_Overlaps,\t"; + if (!Reg.getSubRegs().empty()) + OS << Reg.getName() << "_SubRegsSet,\t"; + else + OS << "Empty_SubRegsSet,\t"; + if (!Reg.getSuperRegs().empty()) + OS << Reg.getName() << "_SuperRegsSet"; + else + OS << "Empty_SuperRegsSet"; + OS << " },\n"; + } + OS << " };\n"; // End of register descriptors... + + OS << "}\n\n"; // End of anonymous namespace... + + // MCRegisterInfo initialization routine. + OS << "void " << "Init" << TargetName + << "MCRegisterInfo(MCRegisterInfo *RI) {\n"; + OS << " RI->InitMCRegisterInfo(" << TargetName << "RegDesc, " + << Regs.size()+1 << ");\n}\n\n"; + + OS << "} // End llvm namespace \n"; +} diff --git a/utils/TableGen/RegisterInfoEmitter.h b/utils/TableGen/RegisterInfoEmitter.h index 1456b4f..6bf14b2 100644 --- a/utils/TableGen/RegisterInfoEmitter.h +++ b/utils/TableGen/RegisterInfoEmitter.h @@ -33,6 +33,9 @@ public: // runEnums - Print out enum values for all of the registers. void runEnums(raw_ostream &o); + + // runDesc - Print out register descriptions. + void runDesc(raw_ostream &o); }; } // End llvm namespace diff --git a/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp index 39fe993..b11ef6f 100644 --- a/utils/TableGen/TableGen.cpp +++ b/utils/TableGen/TableGen.cpp @@ -54,7 +54,7 @@ using namespace llvm; enum ActionType { PrintRecords, GenEmitter, - GenRegisterEnums, GenRegister, GenRegisterHeader, + GenRegisterEnums, GenRegisterDesc, GenRegisterInfo, GenRegisterInfoHeader, GenInstrEnums, GenInstrs, GenAsmWriter, GenAsmMatcher, GenARMDecoder, GenDisassembler, @@ -95,10 +95,12 @@ namespace { "Generate machine code emitter"), clEnumValN(GenRegisterEnums, "gen-register-enums", "Generate enum values for registers"), - clEnumValN(GenRegister, "gen-register-desc", - "Generate a register info description"), - clEnumValN(GenRegisterHeader, "gen-register-desc-header", - "Generate a register info description header"), + clEnumValN(GenRegisterDesc, "gen-register-desc", + "Generate register descriptions"), + clEnumValN(GenRegisterInfo, "gen-register-info", + "Generate registers & reg-classes info"), + clEnumValN(GenRegisterInfoHeader, "gen-register-info-header", + "Generate registers & reg-classes info header"), clEnumValN(GenInstrEnums, "gen-instr-enums", "Generate enum values for instructions"), clEnumValN(GenInstrs, "gen-instr-desc", @@ -261,14 +263,16 @@ int main(int argc, char **argv) { case GenEmitter: CodeEmitterGen(Records).run(Out.os()); break; - case GenRegisterEnums: RegisterInfoEmitter(Records).runEnums(Out.os()); break; - case GenRegister: + case GenRegisterDesc: + RegisterInfoEmitter(Records).runDesc(Out.os()); + break; + case GenRegisterInfo: RegisterInfoEmitter(Records).run(Out.os()); break; - case GenRegisterHeader: + case GenRegisterInfoHeader: RegisterInfoEmitter(Records).runHeader(Out.os()); break; case GenInstrEnums: -- cgit v1.1 From 6db5d55ec335fe442bf9db209be2c4ff50681bbd Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Fri, 24 Jun 2011 05:04:48 +0000 Subject: Fix CellSPU CMakeLists.txt git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133787 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/CellSPU/CMakeLists.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/Target/CellSPU/CMakeLists.txt b/lib/Target/CellSPU/CMakeLists.txt index a2a2ef1..471ea3c 100644 --- a/lib/Target/CellSPU/CMakeLists.txt +++ b/lib/Target/CellSPU/CMakeLists.txt @@ -4,8 +4,9 @@ tablegen(SPUGenInstrNames.inc -gen-instr-enums) tablegen(SPUGenRegisterNames.inc -gen-register-enums) tablegen(SPUGenAsmWriter.inc -gen-asm-writer) tablegen(SPUGenCodeEmitter.inc -gen-emitter) -tablegen(SPUGenRegisterInfo.h.inc -gen-register-desc-header) -tablegen(SPUGenRegisterInfo.inc -gen-register-desc) +tablegen(SPUGenRegisterDesc.inc -gen-register-info) +tablegen(SPUGenRegisterInfo.h.inc -gen-register-info-header) +tablegen(SPUGenRegisterInfo.inc -gen-register-info) tablegen(SPUGenInstrInfo.inc -gen-instr-desc) tablegen(SPUGenDAGISel.inc -gen-dag-isel) tablegen(SPUGenSubtarget.inc -gen-subtarget) -- cgit v1.1 From 5c10b63969a758992dccc830fa0c64a77e80d8d5 Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Fri, 24 Jun 2011 11:03:31 +0000 Subject: Make the generated InitXXXMCRegisterInfo function "static inline", so it doesn't get emitted into multiple object files. This caused linker errors when linking both libLLVMX86Desc and libLLVMX86CodeGen into a single binary (for example when building a monolithic libLLVM shared library). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133791 91177308-0d34-0410-b5e6-96231b3b80d8 --- utils/TableGen/RegisterInfoEmitter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp index 997f1c0..5b25f82 100644 --- a/utils/TableGen/RegisterInfoEmitter.cpp +++ b/utils/TableGen/RegisterInfoEmitter.cpp @@ -709,7 +709,7 @@ void RegisterInfoEmitter::runDesc(raw_ostream &OS) { OS << "}\n\n"; // End of anonymous namespace... // MCRegisterInfo initialization routine. - OS << "void " << "Init" << TargetName + OS << "static inline void Init" << TargetName << "MCRegisterInfo(MCRegisterInfo *RI) {\n"; OS << " RI->InitMCRegisterInfo(" << TargetName << "RegDesc, " << Regs.size()+1 << ");\n}\n\n"; -- cgit v1.1 From ce117be633ae705f0d5be92dee099eb8db1a9844 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Fri, 24 Jun 2011 13:58:45 +0000 Subject: Fix CellSPU CMakeList.txt. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133792 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/CellSPU/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Target/CellSPU/CMakeLists.txt b/lib/Target/CellSPU/CMakeLists.txt index 471ea3c..dc1f708 100644 --- a/lib/Target/CellSPU/CMakeLists.txt +++ b/lib/Target/CellSPU/CMakeLists.txt @@ -4,7 +4,7 @@ tablegen(SPUGenInstrNames.inc -gen-instr-enums) tablegen(SPUGenRegisterNames.inc -gen-register-enums) tablegen(SPUGenAsmWriter.inc -gen-asm-writer) tablegen(SPUGenCodeEmitter.inc -gen-emitter) -tablegen(SPUGenRegisterDesc.inc -gen-register-info) +tablegen(SPUGenRegisterDesc.inc -gen-register-desc) tablegen(SPUGenRegisterInfo.h.inc -gen-register-info-header) tablegen(SPUGenRegisterInfo.inc -gen-register-info) tablegen(SPUGenInstrInfo.inc -gen-instr-desc) -- cgit v1.1 From 1f71549a2ef24fc5d0fc9f0bb3b49fda770fe3d2 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Fri, 24 Jun 2011 14:04:13 +0000 Subject: Simplify now that blocks with phis are not considered simple. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133793 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/TailDuplication.cpp | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/lib/CodeGen/TailDuplication.cpp b/lib/CodeGen/TailDuplication.cpp index 3111d59..33795c3 100644 --- a/lib/CodeGen/TailDuplication.cpp +++ b/lib/CodeGen/TailDuplication.cpp @@ -659,21 +659,6 @@ TailDuplicatePass::duplicateSimpleBB(MachineBasicBlock *TailBB, MachineBasicBlock *NewTarget = *TailBB->succ_begin(); MachineBasicBlock *NextBB = llvm::next(MachineFunction::iterator(PredBB)); - DenseMap LocalVRMap; - SmallVector, 4> CopyInfos; - for (MachineBasicBlock::iterator I = TailBB->begin(); - I != TailBB->end() && I->isPHI();) { - MachineInstr *MI = &*I; - ++I; - ProcessPHI(MI, TailBB, PredBB, LocalVRMap, CopyInfos, UsedByPhi, true); - } - MachineBasicBlock::iterator Loc = PredBB->getFirstTerminator(); - for (unsigned i = 0, e = CopyInfos.size(); i != e; ++i) { - Copies.push_back(BuildMI(*PredBB, Loc, DebugLoc(), - TII->get(TargetOpcode::COPY), - CopyInfos[i].first).addReg(CopyInfos[i].second)); - } - // Make PredFBB explicit. if (PredCond.empty()) PredFBB = PredTBB; -- cgit v1.1 From d7f35fa824165eea799a583ff5af678f2d842b87 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Fri, 24 Jun 2011 15:47:41 +0000 Subject: Now that bb with phis are not considered simple, duplicate them even if we cannot duplicate to every predecessor. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133797 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/TailDuplication.cpp | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/lib/CodeGen/TailDuplication.cpp b/lib/CodeGen/TailDuplication.cpp index 33795c3..c798dd2 100644 --- a/lib/CodeGen/TailDuplication.cpp +++ b/lib/CodeGen/TailDuplication.cpp @@ -98,7 +98,7 @@ namespace { bool IsSimple, MachineBasicBlock &TailBB); bool isSimpleBB(MachineBasicBlock *TailBB); bool canCompletelyDuplicateBB(MachineBasicBlock &BB, bool IsSimple); - void duplicateSimpleBB(MachineBasicBlock *TailBB, + bool duplicateSimpleBB(MachineBasicBlock *TailBB, SmallVector &TDBBs, const DenseSet &RegsUsedByPhi, SmallVector &Copies); @@ -568,7 +568,7 @@ TailDuplicatePass::shouldTailDuplicate(const MachineFunction &MF, return true; if (IsSimple) - return canCompletelyDuplicateBB(TailBB, IsSimple); + return true; if (!PreRegAlloc) return true; @@ -635,24 +635,32 @@ TailDuplicatePass::canCompletelyDuplicateBB(MachineBasicBlock &BB, return true; } -void +bool TailDuplicatePass::duplicateSimpleBB(MachineBasicBlock *TailBB, SmallVector &TDBBs, const DenseSet &UsedByPhi, SmallVector &Copies) { + SmallPtrSet Succs(TailBB->succ_begin(), + TailBB->succ_end()); SmallVector Preds(TailBB->pred_begin(), TailBB->pred_end()); + bool Changed = false; for (SmallSetVector::iterator PI = Preds.begin(), PE = Preds.end(); PI != PE; ++PI) { MachineBasicBlock *PredBB = *PI; + if (PredBB->getLandingPadSuccessor()) + continue; + + if (bothUsedInPHI(*PredBB, Succs)) + continue; + MachineBasicBlock *PredTBB = NULL, *PredFBB = NULL; SmallVector PredCond; - bool NotAnalyzable = - TII->AnalyzeBranch(*PredBB, PredTBB, PredFBB, PredCond, true); - (void)NotAnalyzable; - assert(!NotAnalyzable && "Cannot duplicate this!"); + if (TII->AnalyzeBranch(*PredBB, PredTBB, PredFBB, PredCond, true)) + continue; + Changed = true; DEBUG(dbgs() << "\nTail-duplicating into PredBB: " << *PredBB << "From simple Succ: " << *TailBB); @@ -700,6 +708,7 @@ TailDuplicatePass::duplicateSimpleBB(MachineBasicBlock *TailBB, TDBBs.push_back(PredBB); } + return Changed; } /// TailDuplicate - If it is profitable, duplicate TailBB's contents in each @@ -718,11 +727,8 @@ TailDuplicatePass::TailDuplicate(MachineBasicBlock *TailBB, MachineFunction &MF, DenseSet UsedByPhi; getRegsUsedByPHIs(*TailBB, &UsedByPhi); - if (IsSimple) { - duplicateSimpleBB(TailBB, TDBBs, UsedByPhi, Copies); - return true; - } - + if (IsSimple) + return duplicateSimpleBB(TailBB, TDBBs, UsedByPhi, Copies); // Iterate through all the unique predecessors and tail-duplicate this // block into them, if possible. Copying the list ahead of time also -- cgit v1.1 From 40179bf8748b2729d6c733022428dfa1061325c9 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Fri, 24 Jun 2011 15:50:56 +0000 Subject: Simplify git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133798 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/TailDuplication.cpp | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/lib/CodeGen/TailDuplication.cpp b/lib/CodeGen/TailDuplication.cpp index c798dd2..906a6f5 100644 --- a/lib/CodeGen/TailDuplication.cpp +++ b/lib/CodeGen/TailDuplication.cpp @@ -97,7 +97,7 @@ namespace { bool shouldTailDuplicate(const MachineFunction &MF, bool IsSimple, MachineBasicBlock &TailBB); bool isSimpleBB(MachineBasicBlock *TailBB); - bool canCompletelyDuplicateBB(MachineBasicBlock &BB, bool IsSimple); + bool canCompletelyDuplicateBB(MachineBasicBlock &BB); bool duplicateSimpleBB(MachineBasicBlock *TailBB, SmallVector &TDBBs, const DenseSet &RegsUsedByPhi, @@ -573,7 +573,7 @@ TailDuplicatePass::shouldTailDuplicate(const MachineFunction &MF, if (!PreRegAlloc) return true; - return canCompletelyDuplicateBB(TailBB, IsSimple); + return canCompletelyDuplicateBB(TailBB); } /// isSimpleBB - True if this BB has only one unconditional jump. @@ -606,30 +606,22 @@ bothUsedInPHI(const MachineBasicBlock &A, } bool -TailDuplicatePass::canCompletelyDuplicateBB(MachineBasicBlock &BB, - bool isSimple) { +TailDuplicatePass::canCompletelyDuplicateBB(MachineBasicBlock &BB) { SmallPtrSet Succs(BB.succ_begin(), BB.succ_end()); for (MachineBasicBlock::pred_iterator PI = BB.pred_begin(), PE = BB.pred_end(); PI != PE; ++PI) { MachineBasicBlock *PredBB = *PI; - if (isSimple) { - if (PredBB->getLandingPadSuccessor()) - return false; - if (bothUsedInPHI(*PredBB, Succs)) - return false; - } else { - if (PredBB->succ_size() > 1) - return false; - } + if (PredBB->succ_size() > 1) + return false; MachineBasicBlock *PredTBB = NULL, *PredFBB = NULL; SmallVector PredCond; if (TII->AnalyzeBranch(*PredBB, PredTBB, PredFBB, PredCond, true)) return false; - if (!isSimple && !PredCond.empty()) + if (!PredCond.empty()) return false; } return true; -- cgit v1.1 From 35f4fb34ff60b8f23b2c9691b312bc67cac95eb4 Mon Sep 17 00:00:00 2001 From: Justin Holewinski Date: Fri, 24 Jun 2011 16:27:49 +0000 Subject: PTX: Re-work target sm/compute selection and add some basic GPU targets: g80, gt200, gf100(fermi) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133799 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/PTX/PTX.td | 79 +++++++++++++++++++++++++++++--------- lib/Target/PTX/PTXAsmPrinter.cpp | 2 +- lib/Target/PTX/PTXISelLowering.cpp | 2 +- lib/Target/PTX/PTXInstrInfo.td | 30 ++++++++------- lib/Target/PTX/PTXSubtarget.cpp | 18 +++++++-- lib/Target/PTX/PTXSubtarget.h | 37 ++++++++++++++---- 6 files changed, 121 insertions(+), 47 deletions(-) diff --git a/lib/Target/PTX/PTX.td b/lib/Target/PTX/PTX.td index 6a36b24..f6fbe9f 100644 --- a/lib/Target/PTX/PTX.td +++ b/lib/Target/PTX/PTX.td @@ -30,31 +30,51 @@ def FeatureNoFMA : SubtargetFeature<"no-fma","SupportsFMA", "false", //===- PTX Version --------------------------------------------------------===// def FeaturePTX20 : SubtargetFeature<"ptx20", "PTXVersion", "PTX_VERSION_2_0", - "Use PTX Language Version 2.0", - []>; + "Use PTX Language Version 2.0">; def FeaturePTX21 : SubtargetFeature<"ptx21", "PTXVersion", "PTX_VERSION_2_1", - "Use PTX Language Version 2.1", - [FeaturePTX20]>; + "Use PTX Language Version 2.1">; def FeaturePTX22 : SubtargetFeature<"ptx22", "PTXVersion", "PTX_VERSION_2_2", - "Use PTX Language Version 2.2", - [FeaturePTX21]>; + "Use PTX Language Version 2.2">; def FeaturePTX23 : SubtargetFeature<"ptx23", "PTXVersion", "PTX_VERSION_2_3", - "Use PTX Language Version 2.3", - [FeaturePTX22]>; - -//===- PTX Shader Model ---------------------------------------------------===// - -def FeatureSM10 : SubtargetFeature<"sm10", "PTXShaderModel", "PTX_SM_1_0", - "Enable Shader Model 1.0 compliance">; -def FeatureSM13 : SubtargetFeature<"sm13", "PTXShaderModel", "PTX_SM_1_3", - "Enable Shader Model 1.3 compliance", - [FeatureSM10, FeatureDouble]>; -def FeatureSM20 : SubtargetFeature<"sm20", "PTXShaderModel", "PTX_SM_2_0", - "Enable Shader Model 2.0 compliance", - [FeatureSM13]>; + "Use PTX Language Version 2.3">; + +//===- PTX Target ---------------------------------------------------------===// + +def FeatureSM10 : SubtargetFeature<"sm10", "PTXTarget", "PTX_SM_1_0", + "Use Shader Model 1.0">; +def FeatureSM11 : SubtargetFeature<"sm11", "PTXTarget", "PTX_SM_1_1", + "Use Shader Model 1.1">; +def FeatureSM12 : SubtargetFeature<"sm12", "PTXTarget", "PTX_SM_1_2", + "Use Shader Model 1.2">; +def FeatureSM13 : SubtargetFeature<"sm13", "PTXTarget", "PTX_SM_1_3", + "Use Shader Model 1.3">; +def FeatureSM20 : SubtargetFeature<"sm20", "PTXTarget", "PTX_SM_2_0", + "Use Shader Model 2.0">; +def FeatureSM21 : SubtargetFeature<"sm21", "PTXTarget", "PTX_SM_2_1", + "Use Shader Model 2.1">; +def FeatureSM22 : SubtargetFeature<"sm22", "PTXTarget", "PTX_SM_2_2", + "Use Shader Model 2.2">; +def FeatureSM23 : SubtargetFeature<"sm23", "PTXTarget", "PTX_SM_2_3", + "Use Shader Model 2.3">; + +def FeatureCOMPUTE10 : SubtargetFeature<"compute10", "PTXTarget", + "PTX_COMPUTE_1_0", + "Use Compute Compatibility 1.0">; +def FeatureCOMPUTE11 : SubtargetFeature<"compute11", "PTXTarget", + "PTX_COMPUTE_1_1", + "Use Compute Compatibility 1.1">; +def FeatureCOMPUTE12 : SubtargetFeature<"compute12", "PTXTarget", + "PTX_COMPUTE_1_2", + "Use Compute Compatibility 1.2">; +def FeatureCOMPUTE13 : SubtargetFeature<"compute13", "PTXTarget", + "PTX_COMPUTE_1_3", + "Use Compute Compatibility 1.3">; +def FeatureCOMPUTE20 : SubtargetFeature<"compute20", "PTXTarget", + "PTX_COMPUTE_2_0", + "Use Compute Compatibility 2.0">; //===----------------------------------------------------------------------===// // PTX supported processors @@ -65,6 +85,27 @@ class Proc Features> def : Proc<"generic", []>; +// Processor definitions for compute/shader models +def : Proc<"compute_10", [FeatureCOMPUTE10]>; +def : Proc<"compute_11", [FeatureCOMPUTE11]>; +def : Proc<"compute_12", [FeatureCOMPUTE12]>; +def : Proc<"compute_13", [FeatureCOMPUTE13]>; +def : Proc<"compute_20", [FeatureCOMPUTE20]>; +def : Proc<"sm_10", [FeatureSM10]>; +def : Proc<"sm_11", [FeatureSM11]>; +def : Proc<"sm_12", [FeatureSM12]>; +def : Proc<"sm_13", [FeatureSM13]>; +def : Proc<"sm_20", [FeatureSM20]>; +def : Proc<"sm_21", [FeatureSM21]>; +def : Proc<"sm_22", [FeatureSM22]>; +def : Proc<"sm_23", [FeatureSM23]>; + +// Processor definitions for common GPU architectures +def : Proc<"g80", [FeatureSM10]>; +def : Proc<"gt200", [FeatureSM13]>; +def : Proc<"gf100", [FeatureSM20, FeatureDouble]>; +def : Proc<"fermi", [FeatureSM20, FeatureDouble]>; + //===----------------------------------------------------------------------===// // Register File Description //===----------------------------------------------------------------------===// diff --git a/lib/Target/PTX/PTXAsmPrinter.cpp b/lib/Target/PTX/PTXAsmPrinter.cpp index 5d7e4c3..23268d6 100644 --- a/lib/Target/PTX/PTXAsmPrinter.cpp +++ b/lib/Target/PTX/PTXAsmPrinter.cpp @@ -462,7 +462,7 @@ void PTXAsmPrinter::EmitFunctionDeclaration() { if (i != b) { decl += ", "; } - if (isKernel || ST.getShaderModel() >= PTXSubtarget::PTX_SM_2_0) { + if (isKernel || ST.useParamSpaceForDeviceArgs()) { decl += ".param .b"; decl += utostr(*i); decl += " "; diff --git a/lib/Target/PTX/PTXISelLowering.cpp b/lib/Target/PTX/PTXISelLowering.cpp index c821493..6b7954d 100644 --- a/lib/Target/PTX/PTXISelLowering.cpp +++ b/lib/Target/PTX/PTXISelLowering.cpp @@ -213,7 +213,7 @@ SDValue PTXTargetLowering:: // We do one of two things here: // IsKernel || SM >= 2.0 -> Use param space for arguments // SM < 2.0 -> Use registers for arguments - if (MFI->isKernel() || ST.getShaderModel() >= PTXSubtarget::PTX_SM_2_0) { + if (MFI->isKernel() || ST.useParamSpaceForDeviceArgs()) { // We just need to emit the proper LOAD_PARAM ISDs for (unsigned i = 0, e = Ins.size(); i != e; ++i) { diff --git a/lib/Target/PTX/PTXInstrInfo.td b/lib/Target/PTX/PTXInstrInfo.td index 1c18c4a..a6c03e5 100644 --- a/lib/Target/PTX/PTXInstrInfo.td +++ b/lib/Target/PTX/PTXInstrInfo.td @@ -26,10 +26,10 @@ def Use32BitAddresses : Predicate<"!getSubtarget().is64Bit()">; def Use64BitAddresses : Predicate<"getSubtarget().is64Bit()">; // Shader Model Support -def SupportsSM13 : Predicate<"getSubtarget().supportsSM13()">; -def DoesNotSupportSM13 : Predicate<"!getSubtarget().supportsSM13()">; -def SupportsSM20 : Predicate<"getSubtarget().supportsSM20()">; -def DoesNotSupportSM20 : Predicate<"!getSubtarget().supportsSM20()">; +def FDivNeedsRoundingMode : Predicate<"getSubtarget().fdivNeedsRoundingMode()">; +def FDivNoRoundingMode : Predicate<"!getSubtarget().fdivNeedsRoundingMode()">; +def FMadNeedsRoundingMode : Predicate<"getSubtarget().fmadNeedsRoundingMode()">; +def FMadNoRoundingMode : Predicate<"!getSubtarget().fmadNeedsRoundingMode()">; // PTX Version Support def SupportsPTX21 : Predicate<"getSubtarget().supportsPTX21()">; @@ -613,43 +613,43 @@ def FDIVrr32SM13 : InstPTX<(outs RegF32:$d), (ins RegF32:$a, RegF32:$b), "div.rn.f32\t$d, $a, $b", [(set RegF32:$d, (fdiv RegF32:$a, RegF32:$b))]>, - Requires<[SupportsSM13]>; + Requires<[FDivNeedsRoundingMode]>; def FDIVri32SM13 : InstPTX<(outs RegF32:$d), (ins RegF32:$a, f32imm:$b), "div.rn.f32\t$d, $a, $b", [(set RegF32:$d, (fdiv RegF32:$a, fpimm:$b))]>, - Requires<[SupportsSM13]>; + Requires<[FDivNeedsRoundingMode]>; def FDIVrr32SM10 : InstPTX<(outs RegF32:$d), (ins RegF32:$a, RegF32:$b), "div.f32\t$d, $a, $b", [(set RegF32:$d, (fdiv RegF32:$a, RegF32:$b))]>, - Requires<[DoesNotSupportSM13]>; + Requires<[FDivNoRoundingMode]>; def FDIVri32SM10 : InstPTX<(outs RegF32:$d), (ins RegF32:$a, f32imm:$b), "div.f32\t$d, $a, $b", [(set RegF32:$d, (fdiv RegF32:$a, fpimm:$b))]>, - Requires<[DoesNotSupportSM13]>; + Requires<[FDivNoRoundingMode]>; def FDIVrr64SM13 : InstPTX<(outs RegF64:$d), (ins RegF64:$a, RegF64:$b), "div.rn.f64\t$d, $a, $b", [(set RegF64:$d, (fdiv RegF64:$a, RegF64:$b))]>, - Requires<[SupportsSM13]>; + Requires<[FDivNeedsRoundingMode]>; def FDIVri64SM13 : InstPTX<(outs RegF64:$d), (ins RegF64:$a, f64imm:$b), "div.rn.f64\t$d, $a, $b", [(set RegF64:$d, (fdiv RegF64:$a, fpimm:$b))]>, - Requires<[SupportsSM13]>; + Requires<[FDivNeedsRoundingMode]>; def FDIVrr64SM10 : InstPTX<(outs RegF64:$d), (ins RegF64:$a, RegF64:$b), "div.f64\t$d, $a, $b", [(set RegF64:$d, (fdiv RegF64:$a, RegF64:$b))]>, - Requires<[DoesNotSupportSM13]>; + Requires<[FDivNoRoundingMode]>; def FDIVri64SM10 : InstPTX<(outs RegF64:$d), (ins RegF64:$a, f64imm:$b), "div.f64\t$d, $a, $b", [(set RegF64:$d, (fdiv RegF64:$a, fpimm:$b))]>, - Requires<[DoesNotSupportSM13]>; + Requires<[FDivNoRoundingMode]>; @@ -661,8 +661,10 @@ def FDIVri64SM10 : InstPTX<(outs RegF64:$d), // In the short term, mad is supported on all PTX versions and we use a // default rounding mode no matter what shader model or PTX version. // TODO: Allow the rounding mode to be selectable through llc. -defm FMADSM13 : PTX_FLOAT_4OP<"mad.rn", fmul, fadd>, Requires<[SupportsSM13, SupportsFMA]>; -defm FMAD : PTX_FLOAT_4OP<"mad", fmul, fadd>, Requires<[DoesNotSupportSM13, SupportsFMA]>; +defm FMADSM13 : PTX_FLOAT_4OP<"mad.rn", fmul, fadd>, + Requires<[FMadNeedsRoundingMode, SupportsFMA]>; +defm FMAD : PTX_FLOAT_4OP<"mad", fmul, fadd>, + Requires<[FMadNoRoundingMode, SupportsFMA]>; ///===- Floating-Point Intrinsic Instructions -----------------------------===// diff --git a/lib/Target/PTX/PTXSubtarget.cpp b/lib/Target/PTX/PTXSubtarget.cpp index e8a1dfe..77e3431 100644 --- a/lib/Target/PTX/PTXSubtarget.cpp +++ b/lib/Target/PTX/PTXSubtarget.cpp @@ -18,21 +18,31 @@ using namespace llvm; PTXSubtarget::PTXSubtarget(const std::string &TT, const std::string &FS, bool is64Bit) - : PTXShaderModel(PTX_SM_1_0), + : PTXTarget(PTX_COMPUTE_1_0), PTXVersion(PTX_VERSION_2_0), SupportsDouble(false), SupportsFMA(true), - Is64Bit(is64Bit) { + Is64Bit(is64Bit) { std::string TARGET = "generic"; ParseSubtargetFeatures(FS, TARGET); } std::string PTXSubtarget::getTargetString() const { - switch(PTXShaderModel) { - default: llvm_unreachable("Unknown shader model"); + switch(PTXTarget) { + default: llvm_unreachable("Unknown PTX target"); case PTX_SM_1_0: return "sm_10"; + case PTX_SM_1_1: return "sm_11"; + case PTX_SM_1_2: return "sm_12"; case PTX_SM_1_3: return "sm_13"; case PTX_SM_2_0: return "sm_20"; + case PTX_SM_2_1: return "sm_21"; + case PTX_SM_2_2: return "sm_22"; + case PTX_SM_2_3: return "sm_23"; + case PTX_COMPUTE_1_0: return "compute_10"; + case PTX_COMPUTE_1_1: return "compute_11"; + case PTX_COMPUTE_1_2: return "compute_12"; + case PTX_COMPUTE_1_3: return "compute_13"; + case PTX_COMPUTE_2_0: return "compute_20"; } } diff --git a/lib/Target/PTX/PTXSubtarget.h b/lib/Target/PTX/PTXSubtarget.h index 2ebe6cf..58d192b 100644 --- a/lib/Target/PTX/PTXSubtarget.h +++ b/lib/Target/PTX/PTXSubtarget.h @@ -23,10 +23,23 @@ namespace llvm { /** * Enumeration of Shader Models supported by the back-end. */ - enum PTXShaderModelEnum { + enum PTXTargetEnum { + PTX_COMPUTE_1_0, /*< Compute Compatibility 1.0 */ + PTX_COMPUTE_1_1, /*< Compute Compatibility 1.1 */ + PTX_COMPUTE_1_2, /*< Compute Compatibility 1.2 */ + PTX_COMPUTE_1_3, /*< Compute Compatibility 1.3 */ + PTX_COMPUTE_2_0, /*< Compute Compatibility 2.0 */ + PTX_LAST_COMPUTE, + PTX_SM_1_0, /*< Shader Model 1.0 */ + PTX_SM_1_1, /*< Shader Model 1.1 */ + PTX_SM_1_2, /*< Shader Model 1.2 */ PTX_SM_1_3, /*< Shader Model 1.3 */ - PTX_SM_2_0 /*< Shader Model 2.0 */ + PTX_SM_2_0, /*< Shader Model 2.0 */ + PTX_SM_2_1, /*< Shader Model 2.1 */ + PTX_SM_2_2, /*< Shader Model 2.2 */ + PTX_SM_2_3, /*< Shader Model 2.3 */ + PTX_LAST_SM }; /** @@ -44,7 +57,7 @@ namespace llvm { private: /// Shader Model supported on the target GPU. - PTXShaderModelEnum PTXShaderModel; + PTXTargetEnum PTXTarget; /// PTX Language Version. PTXVersionEnum PTXVersion; @@ -74,18 +87,26 @@ namespace llvm { bool supportsFMA() const { return SupportsFMA; } - bool supportsSM13() const { return PTXShaderModel >= PTX_SM_1_3; } - - bool supportsSM20() const { return PTXShaderModel >= PTX_SM_2_0; } - bool supportsPTX21() const { return PTXVersion >= PTX_VERSION_2_1; } bool supportsPTX22() const { return PTXVersion >= PTX_VERSION_2_2; } bool supportsPTX23() const { return PTXVersion >= PTX_VERSION_2_3; } - PTXShaderModelEnum getShaderModel() const { return PTXShaderModel; } + bool fdivNeedsRoundingMode() const { + return (PTXTarget >= PTX_SM_1_3 && PTXTarget < PTX_LAST_SM) || + (PTXTarget >= PTX_COMPUTE_1_3 && PTXTarget < PTX_LAST_COMPUTE); + } + + bool fmadNeedsRoundingMode() const { + return (PTXTarget >= PTX_SM_1_3 && PTXTarget < PTX_LAST_SM) || + (PTXTarget >= PTX_COMPUTE_1_3 && PTXTarget < PTX_LAST_COMPUTE); + } + bool useParamSpaceForDeviceArgs() const { + return (PTXTarget >= PTX_SM_2_0 && PTXTarget < PTX_LAST_SM) || + (PTXTarget >= PTX_COMPUTE_2_0 && PTXTarget < PTX_LAST_COMPUTE); + } std::string ParseSubtargetFeatures(const std::string &FS, const std::string &CPU); -- cgit v1.1 From 8b2b713f686a6d4908b73c76759447aa87b62c4a Mon Sep 17 00:00:00 2001 From: Akira Hatanaka Date: Fri, 24 Jun 2011 17:55:19 +0000 Subject: Prevent generation of redundant addiu instructions that compute address of static variables or functions. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133803 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Mips/MipsISelDAGToDAG.cpp | 3 ++- test/CodeGen/Mips/2008-07-15-SmallSection.ll | 2 +- test/CodeGen/Mips/internalfunc.ll | 6 +++--- test/CodeGen/Mips/o32_cc_byval.ll | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/Target/Mips/MipsISelDAGToDAG.cpp b/lib/Target/Mips/MipsISelDAGToDAG.cpp index c35c852..5f0c7e0 100644 --- a/lib/Target/Mips/MipsISelDAGToDAG.cpp +++ b/lib/Target/Mips/MipsISelDAGToDAG.cpp @@ -170,7 +170,8 @@ SelectAddr(SDValue Addr, SDValue &Offset, SDValue &Base) { Addr.getOperand(0).getOpcode() == ISD::LOAD) && Addr.getOperand(1).getOpcode() == MipsISD::Lo) { SDValue LoVal = Addr.getOperand(1); - if (dyn_cast(LoVal.getOperand(0))) { + if (isa(LoVal.getOperand(0)) || + isa(LoVal.getOperand(0))) { Base = Addr.getOperand(0); Offset = LoVal.getOperand(0); return true; diff --git a/test/CodeGen/Mips/2008-07-15-SmallSection.ll b/test/CodeGen/Mips/2008-07-15-SmallSection.ll index 91efd68..4795e47 100644 --- a/test/CodeGen/Mips/2008-07-15-SmallSection.ll +++ b/test/CodeGen/Mips/2008-07-15-SmallSection.ll @@ -7,7 +7,7 @@ ; RUN: not grep {sbss} %t1 ; RUN: not grep {gp_rel} %t1 ; RUN: grep {\%hi} %t1 | count 2 -; RUN: grep {\%lo} %t1 | count 2 +; RUN: grep {\%lo} %t1 | count 3 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-unknown-psp-elf" diff --git a/test/CodeGen/Mips/internalfunc.ll b/test/CodeGen/Mips/internalfunc.ll index 50d0993..c2a4e5c 100644 --- a/test/CodeGen/Mips/internalfunc.ll +++ b/test/CodeGen/Mips/internalfunc.ll @@ -15,7 +15,7 @@ entry: define void @caller(i32 %a0, i32 %a1) nounwind { entry: ; CHECK: lw $[[R1:[0-9]+]], %got(caller.sf1)($gp) -; CHECK: addiu ${{[0-9]+}}, $[[R1]], %lo(caller.sf1) +; CHECK: lw $25, %lo(caller.sf1)($[[R1]]) %tobool = icmp eq i32 %a1, 0 br i1 %tobool, label %if.end, label %if.then @@ -26,9 +26,9 @@ if.then: ; preds = %entry if.end: ; preds = %entry, %if.then ; CHECK: lw $[[R2:[0-9]+]], %got(sf2)($gp) -; CHECK: lw $[[R3:[0-9]+]], %got(caller.sf1)($gp) ; CHECK: addiu ${{[0-9]+}}, $[[R2]], %lo(sf2) -; CHECK: addiu ${{[0-9]+}}, $[[R3]], %lo(caller.sf1) +; CHECK: lw $[[R3:[0-9]+]], %got(caller.sf1)($gp) +; CHECK: sw ${{[0-9]+}}, %lo(caller.sf1)($[[R3]]) %tobool3 = icmp ne i32 %a0, 0 %tmp4 = load void (...)** @gf1, align 4 %cond = select i1 %tobool3, void (...)* %tmp4, void (...)* bitcast (void ()* @sf2 to void (...)*) diff --git a/test/CodeGen/Mips/o32_cc_byval.ll b/test/CodeGen/Mips/o32_cc_byval.ll index b78c393..f5e1a87 100644 --- a/test/CodeGen/Mips/o32_cc_byval.ll +++ b/test/CodeGen/Mips/o32_cc_byval.ll @@ -24,7 +24,7 @@ entry: ; CHECK: sw $[[R4]], 28($sp) ; CHECK: sw $[[R5]], 32($sp) ; CHECK: sw $[[R6]], 36($sp) -; CHECK: lw $6, 0($[[R0]]) +; CHECK: lw $6, %lo(f1.s1)($[[R1]]) ; CHECK: lw $7, 4($[[R0]]) %agg.tmp10 = alloca %struct.S3, align 4 call void @callee1(float 2.000000e+01, %struct.S1* byval bitcast (%0* @f1.s1 to %struct.S1*)) nounwind -- cgit v1.1 From 535e58b910199fabcf7db45184bf679e38e42068 Mon Sep 17 00:00:00 2001 From: Jim Grosbach Date: Fri, 24 Jun 2011 18:48:32 +0000 Subject: Fixup info for Thumb2 unconditional branch. rdar://9667872 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133808 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/MC/MachObjectWriter.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/MC/MachObjectWriter.cpp b/lib/MC/MachObjectWriter.cpp index 073a41e..822546e 100644 --- a/lib/MC/MachObjectWriter.cpp +++ b/lib/MC/MachObjectWriter.cpp @@ -1099,6 +1099,7 @@ bool MachObjectWriter::getARMFixupKindMachOInfo(unsigned Kind, Log2Size = llvm::Log2_32(2); return true; + case ARM::fixup_t2_uncondbranch: case ARM::fixup_arm_thumb_bl: case ARM::fixup_arm_thumb_blx: RelocType = unsigned(macho::RIT_ARM_ThumbBranch22Bit); -- cgit v1.1 From 25eba399cb7b4f9691cc63cb3829a00286c70bc4 Mon Sep 17 00:00:00 2001 From: Akira Hatanaka Date: Fri, 24 Jun 2011 19:01:25 +0000 Subject: Change the chain input of nodes that load the address of a function. This change enables SelectionDAG::getLoad at MipsISelLowering.cpp:1914 to return a pre-existing node instead of redundantly create a new node every time it is called. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133811 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Mips/MipsISelLowering.cpp | 5 +---- test/CodeGen/Mips/alloca.ll | 8 +++----- test/CodeGen/Mips/i64arg.ll | 4 ++-- test/CodeGen/Mips/largeimmprinting.ll | 2 +- 4 files changed, 7 insertions(+), 12 deletions(-) diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index 01624c5..e29c8f6 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -1911,7 +1911,7 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee, if (LoadSymAddr) { // Load callee address Callee = DAG.getNode(MipsISD::WrapperPIC, dl, MVT::i32, Callee); - SDValue LoadValue = DAG.getLoad(MVT::i32, dl, Chain, Callee, + SDValue LoadValue = DAG.getLoad(MVT::i32, dl, DAG.getEntryNode(), Callee, MachinePointerInfo::getGOT(), false, false, 0); @@ -1921,9 +1921,6 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee, Callee = DAG.getNode(ISD::ADD, dl, MVT::i32, LoadValue, Lo); } else Callee = LoadValue; - - // Use chain output from LoadValue - Chain = LoadValue.getValue(1); } // copy to T9 diff --git a/test/CodeGen/Mips/alloca.ll b/test/CodeGen/Mips/alloca.ll index ff503ec..fb4f56c 100644 --- a/test/CodeGen/Mips/alloca.ll +++ b/test/CodeGen/Mips/alloca.ll @@ -8,11 +8,9 @@ entry: ; CHECK: subu $[[T2:[0-9]+]], $sp, $[[SZ]] ; CHECK: addu $sp, $zero, $[[T2]] ; CHECK: addiu $[[T3:[0-9]+]], $sp, [[OFF]] -; CHECK: lw $25, %call16(foo)($gp) -; CHECK: addu $4, $zero, $[[T1]] -; CHECK: jalr $25 -; CHECK: lw $25, %call16(foo)($gp) -; CHECK: addu $4, $zero, $[[T3]] +; CHECK: lw $[[T4:[0-9]+]], %call16(foo)($gp) +; CHECK: addu $25, $zero, $[[T4]] +; CHECK: addu $4, $zero, $[[T1]] ; CHECK: jalr $25 %tmp1 = alloca i8, i32 %size, align 4 %add.ptr = getelementptr inbounds i8* %tmp1, i32 5 diff --git a/test/CodeGen/Mips/i64arg.ll b/test/CodeGen/Mips/i64arg.ll index 9a30453..560f2e9 100644 --- a/test/CodeGen/Mips/i64arg.ll +++ b/test/CodeGen/Mips/i64arg.ll @@ -10,8 +10,8 @@ entry: ; CHECK: jalr tail call void @ff1(i32 %i, i64 1085102592623924856) nounwind ; CHECK: lw $25, %call16(ff2) -; CHECK: lw $[[R2:[0-9]+]], 80($sp) -; CHECK: lw $[[R3:[0-9]+]], 84($sp) +; CHECK: lw $[[R2:[0-9]+]], 88($sp) +; CHECK: lw $[[R3:[0-9]+]], 92($sp) ; CHECK: addu $4, $zero, $[[R2]] ; CHECK: addu $5, $zero, $[[R3]] ; CHECK: jalr $25 diff --git a/test/CodeGen/Mips/largeimmprinting.ll b/test/CodeGen/Mips/largeimmprinting.ll index fd7ae9e..fcc20f7 100644 --- a/test/CodeGen/Mips/largeimmprinting.ll +++ b/test/CodeGen/Mips/largeimmprinting.ll @@ -8,7 +8,7 @@ define void @f() nounwind { entry: ; CHECK: lui $at, 65534 ; CHECK: addu $at, $sp, $at -; CHECK: addiu $sp, $at, -16 +; CHECK: addiu $sp, $at, -24 ; CHECK: .cprestore 65536 %agg.tmp = alloca %struct.S1, align 1 -- cgit v1.1 From 4799729d67983b08cac65c55083f7eeffc878b47 Mon Sep 17 00:00:00 2001 From: Justin Holewinski Date: Fri, 24 Jun 2011 19:19:18 +0000 Subject: PTX: Add preliminary support for outputting debug information in the form of .file and .loc directives. Ideally, we would utilize the existing support in AsmPrinter for this, but I cannot find a way to get .file and .loc directives to print without the rest of the associated DWARF sections, which ptxas cannot handle. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133812 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/PTX/PTXAsmPrinter.cpp | 97 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/lib/Target/PTX/PTXAsmPrinter.cpp b/lib/Target/PTX/PTXAsmPrinter.cpp index 23268d6..2848d54 100644 --- a/lib/Target/PTX/PTXAsmPrinter.cpp +++ b/lib/Target/PTX/PTXAsmPrinter.cpp @@ -22,10 +22,12 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Twine.h" +#include "llvm/Analysis/DebugInfo.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/MC/MCContext.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Target/Mangler.h" @@ -35,6 +37,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; @@ -67,6 +70,9 @@ public: const char *Modifier = 0); void printPredicateOperand(const MachineInstr *MI, raw_ostream &O); + unsigned GetOrCreateSourceID(StringRef FileName, + StringRef DirName); + // autogen'd. void printInstruction(const MachineInstr *MI, raw_ostream &OS); static const char *getRegisterName(unsigned RegNo); @@ -74,6 +80,8 @@ public: private: void EmitVariableDeclaration(const GlobalVariable *gv); void EmitFunctionDeclaration(); + + StringMap SourceIdMap; }; // class PTXAsmPrinter } // namespace @@ -175,6 +183,20 @@ void PTXAsmPrinter::EmitStartOfAsmFile(Module &M) OutStreamer.AddBlankLine(); + // Define any .file directives + DebugInfoFinder DbgFinder; + DbgFinder.processModule(M); + + for (DebugInfoFinder::iterator I = DbgFinder.compile_unit_begin(), + E = DbgFinder.compile_unit_end(); I != E; ++I) { + DICompileUnit DIUnit(*I); + StringRef FN = DIUnit.getFilename(); + StringRef Dir = DIUnit.getDirectory(); + GetOrCreateSourceID(FN, Dir); + } + + OutStreamer.AddBlankLine(); + // declare global variables for (Module::const_global_iterator i = M.global_begin(), e = M.global_end(); i != e; ++i) @@ -228,6 +250,54 @@ void PTXAsmPrinter::EmitInstruction(const MachineInstr *MI) { raw_string_ostream OS(str); + DebugLoc DL = MI->getDebugLoc(); + if (!DL.isUnknown()) { + + const MDNode *S = DL.getScope(MF->getFunction()->getContext()); + + // This is taken from DwarfDebug.cpp, which is conveniently not a public + // LLVM class. + StringRef Fn; + StringRef Dir; + unsigned Src = 1; + if (S) { + DIDescriptor Scope(S); + if (Scope.isCompileUnit()) { + DICompileUnit CU(S); + Fn = CU.getFilename(); + Dir = CU.getDirectory(); + } else if (Scope.isFile()) { + DIFile F(S); + Fn = F.getFilename(); + Dir = F.getDirectory(); + } else if (Scope.isSubprogram()) { + DISubprogram SP(S); + Fn = SP.getFilename(); + Dir = SP.getDirectory(); + } else if (Scope.isLexicalBlock()) { + DILexicalBlock DB(S); + Fn = DB.getFilename(); + Dir = DB.getDirectory(); + } else + assert(0 && "Unexpected scope info"); + + Src = GetOrCreateSourceID(Fn, Dir); + } + OutStreamer.EmitDwarfLocDirective(Src, DL.getLine(), DL.getCol(), + 0, 0, 0, Fn); + + const MCDwarfLoc& MDL = OutContext.getCurrentDwarfLoc(); + + OS << "\t.loc "; + OS << utostr(MDL.getFileNum()); + OS << " "; + OS << utostr(MDL.getLine()); + OS << " "; + OS << utostr(MDL.getColumn()); + OS << "\n"; + } + + // Emit predicate printPredicateOperand(MI, OS); @@ -499,6 +569,33 @@ printPredicateOperand(const MachineInstr *MI, raw_ostream &O) { } } +unsigned PTXAsmPrinter::GetOrCreateSourceID(StringRef FileName, + StringRef DirName) { + // If FE did not provide a file name, then assume stdin. + if (FileName.empty()) + return GetOrCreateSourceID("", StringRef()); + + // MCStream expects full path name as filename. + if (!DirName.empty() && !sys::path::is_absolute(FileName)) { + SmallString<128> FullPathName = DirName; + sys::path::append(FullPathName, FileName); + // Here FullPathName will be copied into StringMap by GetOrCreateSourceID. + return GetOrCreateSourceID(StringRef(FullPathName), StringRef()); + } + + StringMapEntry &Entry = SourceIdMap.GetOrCreateValue(FileName); + if (Entry.getValue()) + return Entry.getValue(); + + unsigned SrcId = SourceIdMap.size(); + Entry.setValue(SrcId); + + // Print out a .file directive to specify files for .loc directives. + OutStreamer.EmitDwarfFileDirective(SrcId, Entry.getKey()); + + return SrcId; +} + #include "PTXGenAsmWriter.inc" // Force static initialization. -- cgit v1.1 From ef01edf1e938ef89e598ec558c50ceb2681c5ac4 Mon Sep 17 00:00:00 2001 From: Chad Rosier Date: Fri, 24 Jun 2011 19:23:04 +0000 Subject: The Neon VCVT (between floating-point and fixed-point, Advanced SIMD) instructions can be used to match combinations of multiply/divide and VCVT (between floating-point and integer, Advanced SIMD). Basically the VCVT immediate operand that specifies the number of fraction bits corresponds to a floating-point multiply or divide by the corresponding power of 2. For example, VCVT (floating-point to fixed-point, Advanced SIMD) can replace a combination of VMUL and VCVT (floating-point to integer) as follows: Example (assume d17 = ): vmul.f32 d16, d17, d16 vcvt.s32.f32 d16, d16 becomes: vcvt.s32.f32 d16, d16, #3 Similarly, VCVT (fixed-point to floating-point, Advanced SIMD) can replace a combinations of VCVT (integer to floating-point) and VDIV as follows: Example (assume d17 = ): vcvt.f32.s32 d16, d16 vdiv.f32 d16, d17, d16 becomes: vcvt.f32.s32 d16, d16, #3 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133813 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMISelLowering.cpp | 105 ++++++++++++++++++++++++++++++++++++- test/CodeGen/ARM/vcvt_combine.ll | 99 ++++++++++++++++++++++++++++++++++ test/CodeGen/ARM/vdiv_combine.ll | 102 +++++++++++++++++++++++++++++++++++ 3 files changed, 305 insertions(+), 1 deletion(-) create mode 100644 test/CodeGen/ARM/vcvt_combine.ll create mode 100644 test/CodeGen/ARM/vdiv_combine.ll diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index 4ae4af1..bffaa1c 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -506,6 +506,9 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM) setTargetDAGCombine(ISD::VECTOR_SHUFFLE); setTargetDAGCombine(ISD::INSERT_VECTOR_ELT); setTargetDAGCombine(ISD::STORE); + setTargetDAGCombine(ISD::FP_TO_SINT); + setTargetDAGCombine(ISD::FP_TO_UINT); + setTargetDAGCombine(ISD::FDIV); } computeRegisterProperties(); @@ -6479,7 +6482,104 @@ static SDValue PerformVDUPLANECombine(SDNode *N, return DCI.DAG.getNode(ISD::BITCAST, N->getDebugLoc(), VT, Op); } -/// getVShiftImm - Check if this is a valid build_vector for the immediate +// isConstVecPow2 - Return true if each vector element is a power of 2, all +// elements are the same constant, C, and Log2(C) ranges from 1 to 32. +static bool isConstVecPow2(SDValue ConstVec, bool isSigned, uint64_t &C) +{ + integerPart c0, cN; + for (unsigned I = 0, E = ConstVec.getValueType().getVectorNumElements(); + I != E; I++) { + ConstantFPSDNode *C = dyn_cast(ConstVec.getOperand(I)); + if (!C) + return false; + + bool isExact; + APFloat APF = C->getValueAPF(); + if (APF.convertToInteger(&cN, 64, isSigned, APFloat::rmTowardZero, &isExact) + != APFloat::opOK || !isExact) + return false; + + c0 = (I == 0) ? cN : c0; + if (!isPowerOf2_64(cN) || c0 != cN || Log2_64(c0) < 1 || Log2_64(c0) > 32) + return false; + } + C = c0; + return true; +} + +/// PerformVCVTCombine - VCVT (floating-point to fixed-point, Advanced SIMD) +/// can replace combinations of VMUL and VCVT (floating-point to integer) +/// when the VMUL has a constant operand that is a power of 2. +/// +/// Example (assume d17 = ): +/// vmul.f32 d16, d17, d16 +/// vcvt.s32.f32 d16, d16 +/// becomes: +/// vcvt.s32.f32 d16, d16, #3 +static SDValue PerformVCVTCombine(SDNode *N, + TargetLowering::DAGCombinerInfo &DCI, + const ARMSubtarget *Subtarget) { + SelectionDAG &DAG = DCI.DAG; + SDValue Op = N->getOperand(0); + + if (!Subtarget->hasNEON() || !Op.getValueType().isVector() || + Op.getOpcode() != ISD::FMUL) + return SDValue(); + + uint64_t C; + SDValue N0 = Op->getOperand(0); + SDValue ConstVec = Op->getOperand(1); + bool isSigned = N->getOpcode() == ISD::FP_TO_SINT; + + if (ConstVec.getOpcode() != ISD::BUILD_VECTOR || + !isConstVecPow2(ConstVec, isSigned, C)) + return SDValue(); + + unsigned IntrinsicOpcode = isSigned ? Intrinsic::arm_neon_vcvtfp2fxs : + Intrinsic::arm_neon_vcvtfp2fxu; + return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, N->getDebugLoc(), + N->getValueType(0), + DAG.getConstant(IntrinsicOpcode, MVT::i32), N0, + DAG.getConstant(Log2_64(C), MVT::i32)); +} + +/// PerformVDIVCombine - VCVT (fixed-point to floating-point, Advanced SIMD) +/// can replace combinations of VCVT (integer to floating-point) and VDIV +/// when the VDIV has a constant operand that is a power of 2. +/// +/// Example (assume d17 = ): +/// vcvt.f32.s32 d16, d16 +/// vdiv.f32 d16, d17, d16 +/// becomes: +/// vcvt.f32.s32 d16, d16, #3 +static SDValue PerformVDIVCombine(SDNode *N, + TargetLowering::DAGCombinerInfo &DCI, + const ARMSubtarget *Subtarget) { + SelectionDAG &DAG = DCI.DAG; + SDValue Op = N->getOperand(0); + unsigned OpOpcode = Op.getNode()->getOpcode(); + + if (!Subtarget->hasNEON() || !N->getValueType(0).isVector() || + (OpOpcode != ISD::SINT_TO_FP && OpOpcode != ISD::UINT_TO_FP)) + return SDValue(); + + uint64_t C; + SDValue ConstVec = N->getOperand(1); + bool isSigned = OpOpcode == ISD::SINT_TO_FP; + + if (ConstVec.getOpcode() != ISD::BUILD_VECTOR || + !isConstVecPow2(ConstVec, isSigned, C)) + return SDValue(); + + unsigned IntrinsicOpcode = isSigned ? Intrinsic::arm_neon_vcvtfxs2fp : + Intrinsic::arm_neon_vcvtfxu2fp; + return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, N->getDebugLoc(), + Op.getValueType(), + DAG.getConstant(IntrinsicOpcode, MVT::i32), + Op.getOperand(0), DAG.getConstant(Log2_64(C), MVT::i32)); +} + +/// Getvshiftimm - Check if this is a valid build_vector for the immediate /// operand of a vector shift operation, where all the elements of the /// build_vector must have the same constant integer value. static bool getVShiftImm(SDValue Op, unsigned ElementBits, int64_t &Cnt) { @@ -6868,6 +6968,9 @@ SDValue ARMTargetLowering::PerformDAGCombine(SDNode *N, case ISD::INSERT_VECTOR_ELT: return PerformInsertEltCombine(N, DCI); case ISD::VECTOR_SHUFFLE: return PerformVECTOR_SHUFFLECombine(N, DCI.DAG); case ARMISD::VDUPLANE: return PerformVDUPLANECombine(N, DCI); + case ISD::FP_TO_SINT: + case ISD::FP_TO_UINT: return PerformVCVTCombine(N, DCI, Subtarget); + case ISD::FDIV: return PerformVDIVCombine(N, DCI, Subtarget); case ISD::INTRINSIC_WO_CHAIN: return PerformIntrinsicCombine(N, DCI.DAG); case ISD::SHL: case ISD::SRA: diff --git a/test/CodeGen/ARM/vcvt_combine.ll b/test/CodeGen/ARM/vcvt_combine.ll new file mode 100644 index 0000000..3009e50 --- /dev/null +++ b/test/CodeGen/ARM/vcvt_combine.ll @@ -0,0 +1,99 @@ +; RUN: llc < %s -mtriple=armv7-apple-ios | FileCheck %s + +@in = global float 0x400921FA00000000, align 4 + +; Test signed conversion. +; CHECK: t0 +; CHECK-NOT: vmul +define void @t0() nounwind { +entry: + %tmp = load float* @in, align 4, !tbaa !0 + %vecinit.i = insertelement <2 x float> undef, float %tmp, i32 0 + %vecinit2.i = insertelement <2 x float> %vecinit.i, float %tmp, i32 1 + %mul.i = fmul <2 x float> %vecinit2.i, + %vcvt.i = fptosi <2 x float> %mul.i to <2 x i32> + tail call void @foo_int32x2_t(<2 x i32> %vcvt.i) nounwind + ret void +} + +declare void @foo_int32x2_t(<2 x i32>) + +; Test unsigned conversion. +; CHECK: t1 +; CHECK-NOT: vmul +define void @t1() nounwind { +entry: + %tmp = load float* @in, align 4, !tbaa !0 + %vecinit.i = insertelement <2 x float> undef, float %tmp, i32 0 + %vecinit2.i = insertelement <2 x float> %vecinit.i, float %tmp, i32 1 + %mul.i = fmul <2 x float> %vecinit2.i, + %vcvt.i = fptoui <2 x float> %mul.i to <2 x i32> + tail call void @foo_uint32x2_t(<2 x i32> %vcvt.i) nounwind + ret void +} + +declare void @foo_uint32x2_t(<2 x i32>) + +; Test which should not fold due to non-power of 2. +; CHECK: t2 +; CHECK: vmul +define void @t2() nounwind { +entry: + %tmp = load float* @in, align 4, !tbaa !0 + %vecinit.i = insertelement <2 x float> undef, float %tmp, i32 0 + %vecinit2.i = insertelement <2 x float> %vecinit.i, float %tmp, i32 1 + %mul.i = fmul <2 x float> %vecinit2.i, + %vcvt.i = fptosi <2 x float> %mul.i to <2 x i32> + tail call void @foo_int32x2_t(<2 x i32> %vcvt.i) nounwind + ret void +} + +; Test which should not fold due to power of 2 out of range. +; CHECK: t3 +; CHECK: vmul +define void @t3() nounwind { +entry: + %tmp = load float* @in, align 4, !tbaa !0 + %vecinit.i = insertelement <2 x float> undef, float %tmp, i32 0 + %vecinit2.i = insertelement <2 x float> %vecinit.i, float %tmp, i32 1 + %mul.i = fmul <2 x float> %vecinit2.i, + %vcvt.i = fptosi <2 x float> %mul.i to <2 x i32> + tail call void @foo_int32x2_t(<2 x i32> %vcvt.i) nounwind + ret void +} + +; Test which case where const is max power of 2 (i.e., 2^32). +; CHECK: t4 +; CHECK-NOT: vmul +define void @t4() nounwind { +entry: + %tmp = load float* @in, align 4, !tbaa !0 + %vecinit.i = insertelement <2 x float> undef, float %tmp, i32 0 + %vecinit2.i = insertelement <2 x float> %vecinit.i, float %tmp, i32 1 + %mul.i = fmul <2 x float> %vecinit2.i, + %vcvt.i = fptosi <2 x float> %mul.i to <2 x i32> + tail call void @foo_int32x2_t(<2 x i32> %vcvt.i) nounwind + ret void +} + +; Test quadword. +; CHECK: t5 +; CHECK-NOT: vmul +define void @t5() nounwind { +entry: + %tmp = load float* @in, align 4, !tbaa !0 + %vecinit.i = insertelement <4 x float> undef, float %tmp, i32 0 + %vecinit2.i = insertelement <4 x float> %vecinit.i, float %tmp, i32 1 + %vecinit4.i = insertelement <4 x float> %vecinit2.i, float %tmp, i32 2 + %vecinit6.i = insertelement <4 x float> %vecinit4.i, float %tmp, i32 3 + %mul.i = fmul <4 x float> %vecinit6.i, + %vcvt.i = fptosi <4 x float> %mul.i to <4 x i32> + tail call void @foo_int32x4_t(<4 x i32> %vcvt.i) nounwind + ret void +} + +declare void @foo_int32x4_t(<4 x i32>) + +!0 = metadata !{metadata !"float", metadata !1} +!1 = metadata !{metadata !"omnipotent char", metadata !2} +!2 = metadata !{metadata !"Simple C/C++ TBAA", null} diff --git a/test/CodeGen/ARM/vdiv_combine.ll b/test/CodeGen/ARM/vdiv_combine.ll new file mode 100644 index 0000000..1387393 --- /dev/null +++ b/test/CodeGen/ARM/vdiv_combine.ll @@ -0,0 +1,102 @@ +; RUN: llc < %s -mtriple=armv7-apple-ios | FileCheck %s + +@in = global float 0x400921FA00000000, align 4 +@iin = global i32 -1023, align 4 +@uin = global i32 1023, align 4 + +declare void @foo_int32x4_t(<4 x i32>) + +; Test signed conversion. +; CHECK: t1 +; CHECK-NOT: vdiv +define void @t1() nounwind { +entry: + %tmp = load i32* @iin, align 4, !tbaa !3 + %vecinit.i = insertelement <2 x i32> undef, i32 %tmp, i32 0 + %vecinit2.i = insertelement <2 x i32> %vecinit.i, i32 %tmp, i32 1 + %vcvt.i = sitofp <2 x i32> %vecinit2.i to <2 x float> + %div.i = fdiv <2 x float> %vcvt.i, + tail call void @foo_float32x2_t(<2 x float> %div.i) nounwind + ret void +} + +declare void @foo_float32x2_t(<2 x float>) + +; Test unsigned conversion. +; CHECK: t2 +; CHECK-NOT: vdiv +define void @t2() nounwind { +entry: + %tmp = load i32* @uin, align 4, !tbaa !3 + %vecinit.i = insertelement <2 x i32> undef, i32 %tmp, i32 0 + %vecinit2.i = insertelement <2 x i32> %vecinit.i, i32 %tmp, i32 1 + %vcvt.i = uitofp <2 x i32> %vecinit2.i to <2 x float> + %div.i = fdiv <2 x float> %vcvt.i, + tail call void @foo_float32x2_t(<2 x float> %div.i) nounwind + ret void +} + +; Test which should not fold due to non-power of 2. +; CHECK: t3 +; CHECK: vdiv +define void @t3() nounwind { +entry: + %tmp = load i32* @iin, align 4, !tbaa !3 + %vecinit.i = insertelement <2 x i32> undef, i32 %tmp, i32 0 + %vecinit2.i = insertelement <2 x i32> %vecinit.i, i32 %tmp, i32 1 + %vcvt.i = sitofp <2 x i32> %vecinit2.i to <2 x float> + %div.i = fdiv <2 x float> %vcvt.i, + tail call void @foo_float32x2_t(<2 x float> %div.i) nounwind + ret void +} + +; Test which should not fold due to power of 2 out of range. +; CHECK: t4 +; CHECK: vdiv +define void @t4() nounwind { +entry: + %tmp = load i32* @iin, align 4, !tbaa !3 + %vecinit.i = insertelement <2 x i32> undef, i32 %tmp, i32 0 + %vecinit2.i = insertelement <2 x i32> %vecinit.i, i32 %tmp, i32 1 + %vcvt.i = sitofp <2 x i32> %vecinit2.i to <2 x float> + %div.i = fdiv <2 x float> %vcvt.i, + tail call void @foo_float32x2_t(<2 x float> %div.i) nounwind + ret void +} + +; Test case where const is max power of 2 (i.e., 2^32). +; CHECK: t5 +; CHECK-NOT: vdiv +define void @t5() nounwind { +entry: + %tmp = load i32* @iin, align 4, !tbaa !3 + %vecinit.i = insertelement <2 x i32> undef, i32 %tmp, i32 0 + %vecinit2.i = insertelement <2 x i32> %vecinit.i, i32 %tmp, i32 1 + %vcvt.i = sitofp <2 x i32> %vecinit2.i to <2 x float> + %div.i = fdiv <2 x float> %vcvt.i, + tail call void @foo_float32x2_t(<2 x float> %div.i) nounwind + ret void +} + +; Test quadword. +; CHECK: t6 +; CHECK-NOT: vdiv +define void @t6() nounwind { +entry: + %tmp = load i32* @iin, align 4, !tbaa !3 + %vecinit.i = insertelement <4 x i32> undef, i32 %tmp, i32 0 + %vecinit2.i = insertelement <4 x i32> %vecinit.i, i32 %tmp, i32 1 + %vecinit4.i = insertelement <4 x i32> %vecinit2.i, i32 %tmp, i32 2 + %vecinit6.i = insertelement <4 x i32> %vecinit4.i, i32 %tmp, i32 3 + %vcvt.i = sitofp <4 x i32> %vecinit6.i to <4 x float> + %div.i = fdiv <4 x float> %vcvt.i, + tail call void @foo_float32x4_t(<4 x float> %div.i) nounwind + ret void +} + +declare void @foo_float32x4_t(<4 x float>) + +!0 = metadata !{metadata !"float", metadata !1} +!1 = metadata !{metadata !"omnipotent char", metadata !2} +!2 = metadata !{metadata !"Simple C/C++ TBAA", null} +!3 = metadata !{metadata !"int", metadata !1} -- cgit v1.1 From b05a8a8f02ee3ec78eb6171f2f3078fe2ed4ff7e Mon Sep 17 00:00:00 2001 From: Dan Bailey Date: Fri, 24 Jun 2011 19:27:10 +0000 Subject: PTX: Add support for i8 type and introduce associated .b8 registers The i8 type is required for boolean values, but can only use ld, st and mov instructions. The i1 type continues to be used for predicates. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133814 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/PTX/PTXAsmPrinter.cpp | 2 + lib/Target/PTX/PTXCallingConv.td | 2 + lib/Target/PTX/PTXISelLowering.cpp | 17 ++++- lib/Target/PTX/PTXInstrInfo.cpp | 9 ++- lib/Target/PTX/PTXInstrInfo.td | 115 ++++++++++++++++++++++++++-- lib/Target/PTX/PTXRegisterInfo.td | 132 +++++++++++++++++++++++++++++++++ lib/Target/PTX/generate-register-td.py | 29 ++++++-- test/CodeGen/PTX/cvt.ll | 83 +++++++++++++++++++++ test/CodeGen/PTX/ld.ll | 77 +++++++++++++++++++ test/CodeGen/PTX/mov.ll | 12 +++ test/CodeGen/PTX/st.ll | 78 +++++++++++++++++++ 11 files changed, 541 insertions(+), 15 deletions(-) diff --git a/lib/Target/PTX/PTXAsmPrinter.cpp b/lib/Target/PTX/PTXAsmPrinter.cpp index 2848d54..c9b2915 100644 --- a/lib/Target/PTX/PTXAsmPrinter.cpp +++ b/lib/Target/PTX/PTXAsmPrinter.cpp @@ -92,6 +92,7 @@ static const char *getRegisterTypeName(unsigned RegNo) { #define TEST_REGCLS(cls, clsstr) \ if (PTX::cls ## RegisterClass->contains(RegNo)) return # clsstr; TEST_REGCLS(RegPred, pred); + TEST_REGCLS(RegI8, b8); TEST_REGCLS(RegI16, b16); TEST_REGCLS(RegI32, b32); TEST_REGCLS(RegI64, b64); @@ -124,6 +125,7 @@ static const char *getTypeName(const Type* type) { case Type::IntegerTyID: switch (type->getPrimitiveSizeInBits()) { default: llvm_unreachable("Unknown integer bit-width"); + case 8: return ".u8"; case 16: return ".u16"; case 32: return ".u32"; case 64: return ".u64"; diff --git a/lib/Target/PTX/PTXCallingConv.td b/lib/Target/PTX/PTXCallingConv.td index 3e3ff48..2de6199 100644 --- a/lib/Target/PTX/PTXCallingConv.td +++ b/lib/Target/PTX/PTXCallingConv.td @@ -15,6 +15,7 @@ // PTX Formal Parameter Calling Convention def CC_PTX : CallingConv<[ CCIfType<[i1], CCAssignToReg<[P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122, P123, P124, P125, P126, P127]>>, + CCIfType<[i8], CCAssignToReg<[RQ12, RQ13, RQ14, RQ15, RQ16, RQ17, RQ18, RQ19, RQ20, RQ21, RQ22, RQ23, RQ24, RQ25, RQ26, RQ27, RQ28, RQ29, RQ30, RQ31, RQ32, RQ33, RQ34, RQ35, RQ36, RQ37, RQ38, RQ39, RQ40, RQ41, RQ42, RQ43, RQ44, RQ45, RQ46, RQ47, RQ48, RQ49, RQ50, RQ51, RQ52, RQ53, RQ54, RQ55, RQ56, RQ57, RQ58, RQ59, RQ60, RQ61, RQ62, RQ63, RQ64, RQ65, RQ66, RQ67, RQ68, RQ69, RQ70, RQ71, RQ72, RQ73, RQ74, RQ75, RQ76, RQ77, RQ78, RQ79, RQ80, RQ81, RQ82, RQ83, RQ84, RQ85, RQ86, RQ87, RQ88, RQ89, RQ90, RQ91, RQ92, RQ93, RQ94, RQ95, RQ96, RQ97, RQ98, RQ99, RQ100, RQ101, RQ102, RQ103, RQ104, RQ105, RQ106, RQ107, RQ108, RQ109, RQ110, RQ111, RQ112, RQ113, RQ114, RQ115, RQ116, RQ117, RQ118, RQ119, RQ120, RQ121, RQ122, RQ123, RQ124, RQ125, RQ126, RQ127]>>, CCIfType<[i16], CCAssignToReg<[RH12, RH13, RH14, RH15, RH16, RH17, RH18, RH19, RH20, RH21, RH22, RH23, RH24, RH25, RH26, RH27, RH28, RH29, RH30, RH31, RH32, RH33, RH34, RH35, RH36, RH37, RH38, RH39, RH40, RH41, RH42, RH43, RH44, RH45, RH46, RH47, RH48, RH49, RH50, RH51, RH52, RH53, RH54, RH55, RH56, RH57, RH58, RH59, RH60, RH61, RH62, RH63, RH64, RH65, RH66, RH67, RH68, RH69, RH70, RH71, RH72, RH73, RH74, RH75, RH76, RH77, RH78, RH79, RH80, RH81, RH82, RH83, RH84, RH85, RH86, RH87, RH88, RH89, RH90, RH91, RH92, RH93, RH94, RH95, RH96, RH97, RH98, RH99, RH100, RH101, RH102, RH103, RH104, RH105, RH106, RH107, RH108, RH109, RH110, RH111, RH112, RH113, RH114, RH115, RH116, RH117, RH118, RH119, RH120, RH121, RH122, RH123, RH124, RH125, RH126, RH127]>>, CCIfType<[i32,f32], CCAssignToReg<[R12, R13, R14, R15, R16, R17, R18, R19, R20, R21, R22, R23, R24, R25, R26, R27, R28, R29, R30, R31, R32, R33, R34, R35, R36, R37, R38, R39, R40, R41, R42, R43, R44, R45, R46, R47, R48, R49, R50, R51, R52, R53, R54, R55, R56, R57, R58, R59, R60, R61, R62, R63, R64, R65, R66, R67, R68, R69, R70, R71, R72, R73, R74, R75, R76, R77, R78, R79, R80, R81, R82, R83, R84, R85, R86, R87, R88, R89, R90, R91, R92, R93, R94, R95, R96, R97, R98, R99, R100, R101, R102, R103, R104, R105, R106, R107, R108, R109, R110, R111, R112, R113, R114, R115, R116, R117, R118, R119, R120, R121, R122, R123, R124, R125, R126, R127]>>, CCIfType<[i64,f64], CCAssignToReg<[RD12, RD13, RD14, RD15, RD16, RD17, RD18, RD19, RD20, RD21, RD22, RD23, RD24, RD25, RD26, RD27, RD28, RD29, RD30, RD31, RD32, RD33, RD34, RD35, RD36, RD37, RD38, RD39, RD40, RD41, RD42, RD43, RD44, RD45, RD46, RD47, RD48, RD49, RD50, RD51, RD52, RD53, RD54, RD55, RD56, RD57, RD58, RD59, RD60, RD61, RD62, RD63, RD64, RD65, RD66, RD67, RD68, RD69, RD70, RD71, RD72, RD73, RD74, RD75, RD76, RD77, RD78, RD79, RD80, RD81, RD82, RD83, RD84, RD85, RD86, RD87, RD88, RD89, RD90, RD91, RD92, RD93, RD94, RD95, RD96, RD97, RD98, RD99, RD100, RD101, RD102, RD103, RD104, RD105, RD106, RD107, RD108, RD109, RD110, RD111, RD112, RD113, RD114, RD115, RD116, RD117, RD118, RD119, RD120, RD121, RD122, RD123, RD124, RD125, RD126, RD127]>> @@ -23,6 +24,7 @@ def CC_PTX : CallingConv<[ // PTX Return Value Calling Convention def RetCC_PTX : CallingConv<[ CCIfType<[i1], CCAssignToReg<[P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11]>>, + CCIfType<[i8], CCAssignToReg<[RQ0, RQ1, RQ2, RQ3, RQ4, RQ5, RQ6, RQ7, RQ8, RQ9, RQ10, RQ11]>>, CCIfType<[i16], CCAssignToReg<[RH0, RH1, RH2, RH3, RH4, RH5, RH6, RH7, RH8, RH9, RH10, RH11]>>, CCIfType<[i32,f32], CCAssignToReg<[R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11]>>, CCIfType<[i64,f64], CCAssignToReg<[RD0, RD1, RD2, RD3, RD4, RD5, RD6, RD7, RD8, RD9, RD10, RD11]>> diff --git a/lib/Target/PTX/PTXISelLowering.cpp b/lib/Target/PTX/PTXISelLowering.cpp index 6b7954d..9b836a5 100644 --- a/lib/Target/PTX/PTXISelLowering.cpp +++ b/lib/Target/PTX/PTXISelLowering.cpp @@ -40,6 +40,7 @@ PTXTargetLowering::PTXTargetLowering(TargetMachine &TM) : TargetLowering(TM, new TargetLoweringObjectFileELF()) { // Set up the register classes. addRegisterClass(MVT::i1, PTX::RegPredRegisterClass); + addRegisterClass(MVT::i8, PTX::RegI8RegisterClass); addRegisterClass(MVT::i16, PTX::RegI16RegisterClass); addRegisterClass(MVT::i32, PTX::RegI32RegisterClass); addRegisterClass(MVT::i64, PTX::RegI64RegisterClass); @@ -52,10 +53,20 @@ PTXTargetLowering::PTXTargetLowering(TargetMachine &TM) setOperationAction(ISD::ConstantFP, MVT::f32, Legal); setOperationAction(ISD::ConstantFP, MVT::f64, Legal); - + + // Promote i1 type + setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote); + setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote); + setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote); + + setTruncStoreAction(MVT::i8, MVT::i1, Promote); + + setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); + // Turn i16 (z)extload into load + (z)extend setLoadExtAction(ISD::EXTLOAD, MVT::i16, Expand); setLoadExtAction(ISD::ZEXTLOAD, MVT::i16, Expand); + setLoadExtAction(ISD::SEXTLOAD, MVT::i16, Expand); // Turn f32 extload into load + fextend setLoadExtAction(ISD::EXTLOAD, MVT::f32, Expand); @@ -176,6 +187,7 @@ struct argmap_entry { bool operator==(MVT::SimpleValueType _VT) const { return VT == _VT; } } argmap[] = { argmap_entry(MVT::i1, PTX::RegPredRegisterClass), + argmap_entry(MVT::i8, PTX::RegI8RegisterClass), argmap_entry(MVT::i16, PTX::RegI16RegisterClass), argmap_entry(MVT::i32, PTX::RegI32RegisterClass), argmap_entry(MVT::i64, PTX::RegI64RegisterClass), @@ -252,6 +264,9 @@ SDValue PTXTargetLowering:: if (RegVT == MVT::i1) { TRC = PTX::RegPredRegisterClass; } + else if (RegVT == MVT::i8) { + TRC = PTX::RegI8RegisterClass; + } else if (RegVT == MVT::i16) { TRC = PTX::RegI16RegisterClass; } diff --git a/lib/Target/PTX/PTXInstrInfo.cpp b/lib/Target/PTX/PTXInstrInfo.cpp index 5bdac89..720d5b1 100644 --- a/lib/Target/PTX/PTXInstrInfo.cpp +++ b/lib/Target/PTX/PTXInstrInfo.cpp @@ -33,6 +33,7 @@ static const struct map_entry { const TargetRegisterClass *cls; const int opcode; } map[] = { + { &PTX::RegI8RegClass, PTX::MOVU8rr }, { &PTX::RegI16RegClass, PTX::MOVU16rr }, { &PTX::RegI32RegClass, PTX::MOVU32rr }, { &PTX::RegI64RegClass, PTX::MOVU64rr }, @@ -302,7 +303,9 @@ void PTXInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, int OpCode; // Select the appropriate opcode based on the register class - if (RC == PTX::RegI16RegisterClass) { + if (RC == PTX::RegI8RegisterClass) { + OpCode = PTX::STACKSTOREI8; + } else if (RC == PTX::RegI16RegisterClass) { OpCode = PTX::STACKSTOREI16; } else if (RC == PTX::RegI32RegisterClass) { OpCode = PTX::STACKSTOREI32; @@ -337,7 +340,9 @@ void PTXInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, int OpCode; // Select the appropriate opcode based on the register class - if (RC == PTX::RegI16RegisterClass) { + if (RC == PTX::RegI8RegisterClass) { + OpCode = PTX::STACKLOADI8; + } else if (RC == PTX::RegI16RegisterClass) { OpCode = PTX::STACKLOADI16; } else if (RC == PTX::RegI32RegisterClass) { OpCode = PTX::STACKLOADI32; diff --git a/lib/Target/PTX/PTXInstrInfo.td b/lib/Target/PTX/PTXInstrInfo.td index a6c03e5..c5cedb0 100644 --- a/lib/Target/PTX/PTXInstrInfo.td +++ b/lib/Target/PTX/PTXInstrInfo.td @@ -537,6 +537,7 @@ multiclass PTX_LD { + defm u8 : PTX_LD; defm u16 : PTX_LD; defm u32 : PTX_LD; defm u64 : PTX_LD; @@ -572,6 +573,7 @@ multiclass PTX_ST { + defm u8 : PTX_ST; defm u16 : PTX_ST; defm u32 : PTX_ST; defm u64 : PTX_ST; @@ -783,22 +785,27 @@ defm XOR : PTX_LOGIC<"xor", xor>; let neverHasSideEffects = 1 in { def MOVPREDrr : InstPTX<(outs RegPred:$d), (ins RegPred:$a), "mov.pred\t$d, $a", []>; + def MOVU8rr + : InstPTX<(outs RegI8:$d), (ins RegI8:$a), "mov.u8\t$d, $a", []>; def MOVU16rr - : InstPTX<(outs RegI16:$d), (ins RegI16:$a), "mov.u16\t$d, $a", []>; + : InstPTX<(outs RegI16:$d), (ins RegI16:$a), "mov.u16\t$d, $a", []>; def MOVU32rr - : InstPTX<(outs RegI32:$d), (ins RegI32:$a), "mov.u32\t$d, $a", []>; + : InstPTX<(outs RegI32:$d), (ins RegI32:$a), "mov.u32\t$d, $a", []>; def MOVU64rr - : InstPTX<(outs RegI64:$d), (ins RegI64:$a), "mov.u64\t$d, $a", []>; + : InstPTX<(outs RegI64:$d), (ins RegI64:$a), "mov.u64\t$d, $a", []>; def MOVF32rr - : InstPTX<(outs RegF32:$d), (ins RegF32:$a), "mov.f32\t$d, $a", []>; + : InstPTX<(outs RegF32:$d), (ins RegF32:$a), "mov.f32\t$d, $a", []>; def MOVF64rr - : InstPTX<(outs RegF64:$d), (ins RegF64:$a), "mov.f64\t$d, $a", []>; + : InstPTX<(outs RegF64:$d), (ins RegF64:$a), "mov.f64\t$d, $a", []>; } let isReMaterializable = 1, isAsCheapAsAMove = 1 in { def MOVPREDri : InstPTX<(outs RegPred:$d), (ins i1imm:$a), "mov.pred\t$d, $a", [(set RegPred:$d, imm:$a)]>; + def MOVU8ri + : InstPTX<(outs RegI8:$d), (ins i8imm:$a), "mov.u8\t$d, $a", + [(set RegI8:$d, imm:$a)]>; def MOVU16ri : InstPTX<(outs RegI16:$d), (ins i16imm:$a), "mov.u16\t$d, $a", [(set RegI16:$d, imm:$a)]>; @@ -838,6 +845,9 @@ let hasSideEffects = 1 in { def LDpiPred : InstPTX<(outs RegPred:$d), (ins MEMpi:$a), "ld.param.pred\t$d, [$a]", [(set RegPred:$d, (PTXloadparam timm:$a))]>; + def LDpiU8 : InstPTX<(outs RegI8:$d), (ins MEMpi:$a), + "ld.param.u8\t$d, [$a]", + [(set RegI8:$d, (PTXloadparam timm:$a))]>; def LDpiU16 : InstPTX<(outs RegI16:$d), (ins MEMpi:$a), "ld.param.u16\t$d, [$a]", [(set RegI16:$d, (PTXloadparam timm:$a))]>; @@ -857,6 +867,9 @@ let hasSideEffects = 1 in { def STpiPred : InstPTX<(outs), (ins MEMret:$d, RegPred:$a), "st.param.pred\t[$d], $a", [(PTXstoreparam timm:$d, RegPred:$a)]>; + def STpiU8 : InstPTX<(outs), (ins MEMret:$d, RegI8:$a), + "st.param.u8\t[$d], $a", + [(PTXstoreparam timm:$d, RegI8:$a)]>; def STpiU16 : InstPTX<(outs), (ins MEMret:$d, RegI16:$a), "st.param.u16\t[$d], $a", [(PTXstoreparam timm:$d, RegI16:$a)]>; @@ -887,6 +900,10 @@ defm STs : PTX_ST_ALL<"st.shared", store_shared>; // PTX does not directly support converting to a predicate type, so we fake it // by performing a greater-than test between the value and zero. This follows // the C convention that any non-zero value is equivalent to 'true'. +def CVT_pred_u8 + : InstPTX<(outs RegPred:$d), (ins RegI8:$a), "setp.gt.b8\t$d, $a, 0", + [(set RegPred:$d, (trunc RegI8:$a))]>; + def CVT_pred_u16 : InstPTX<(outs RegPred:$d), (ins RegI16:$a), "setp.gt.b16\t$d, $a, 0", [(set RegPred:$d, (trunc RegI16:$a))]>; @@ -907,6 +924,34 @@ def CVT_pred_f64 : InstPTX<(outs RegPred:$d), (ins RegF64:$a), "setp.gt.b64\t$d, $a, 0", [(set RegPred:$d, (fp_to_uint RegF64:$a))]>; +// Conversion to u8 +// PTX does not directly support converting a predicate to a value, so we +// use a select instruction to select either 0 or 1 (integer or fp) based +// on the truth value of the predicate. +def CVT_u8_pred + : InstPTX<(outs RegI8:$d), (ins RegPred:$a), "selp.u8\t$d, 1, 0, $a", + [(set RegI8:$d, (zext RegPred:$a))]>; + +def CVT_u8_preds + : InstPTX<(outs RegI8:$d), (ins RegPred:$a), "selp.u8\t$d, 1, 0, $a", + [(set RegI8:$d, (sext RegPred:$a))]>; + +def CVT_u8_u32 + : InstPTX<(outs RegI8:$d), (ins RegI32:$a), "cvt.u8.u32\t$d, $a", + [(set RegI8:$d, (trunc RegI32:$a))]>; + +def CVT_u8_u64 + : InstPTX<(outs RegI8:$d), (ins RegI64:$a), "cvt.u8.u64\t$d, $a", + [(set RegI8:$d, (trunc RegI64:$a))]>; + +def CVT_u8_f32 + : InstPTX<(outs RegI8:$d), (ins RegF32:$a), "cvt.rzi.u8.f32\t$d, $a", + [(set RegI8:$d, (fp_to_uint RegF32:$a))]>; + +def CVT_u8_f64 + : InstPTX<(outs RegI8:$d), (ins RegF64:$a), "cvt.rzi.u8.f64\t$d, $a", + [(set RegI8:$d, (fp_to_uint RegF64:$a))]>; + // Conversion to u16 // PTX does not directly support converting a predicate to a value, so we // use a select instruction to select either 0 or 1 (integer or fp) based @@ -915,6 +960,18 @@ def CVT_u16_pred : InstPTX<(outs RegI16:$d), (ins RegPred:$a), "selp.u16\t$d, 1, 0, $a", [(set RegI16:$d, (zext RegPred:$a))]>; +def CVT_u16_preds + : InstPTX<(outs RegI16:$d), (ins RegPred:$a), "selp.u16\t$d, 1, 0, $a", + [(set RegI16:$d, (sext RegPred:$a))]>; + +def CVT_u16_u8 + : InstPTX<(outs RegI16:$d), (ins RegI8:$a), "cvt.u16.u8\t$d, $a", + [(set RegI16:$d, (zext RegI8:$a))]>; + +def CVT_u16_s8 + : InstPTX<(outs RegI16:$d), (ins RegI8:$a), "cvt.u16.s8\t$d, $a", + [(set RegI16:$d, (sext RegI8:$a))]>; + def CVT_u16_u32 : InstPTX<(outs RegI16:$d), (ins RegI32:$a), "cvt.u16.u32\t$d, $a", [(set RegI16:$d, (trunc RegI32:$a))]>; @@ -937,10 +994,26 @@ def CVT_u32_pred : InstPTX<(outs RegI32:$d), (ins RegPred:$a), "selp.u32\t$d, 1, 0, $a", [(set RegI32:$d, (zext RegPred:$a))]>; +def CVT_u32_u8 + : InstPTX<(outs RegI32:$d), (ins RegI8:$a), "cvt.u32.u8\t$d, $a", + [(set RegI32:$d, (zext RegI8:$a))]>; + def CVT_u32_u16 : InstPTX<(outs RegI32:$d), (ins RegI16:$a), "cvt.u32.u16\t$d, $a", [(set RegI32:$d, (zext RegI16:$a))]>; +def CVT_u32_preds + : InstPTX<(outs RegI32:$d), (ins RegPred:$a), "selp.u32\t$d, 1, 0, $a", + [(set RegI32:$d, (sext RegPred:$a))]>; + +def CVT_u32_s8 + : InstPTX<(outs RegI32:$d), (ins RegI8:$a), "cvt.u32.s8\t$d, $a", + [(set RegI32:$d, (zext RegI8:$a))]>; + +def CVT_u32_s16 + : InstPTX<(outs RegI32:$d), (ins RegI16:$a), "cvt.u32.s16\t$d, $a", + [(set RegI32:$d, (sext RegI16:$a))]>; + def CVT_u32_u64 : InstPTX<(outs RegI32:$d), (ins RegI64:$a), "cvt.u32.u64\t$d, $a", [(set RegI32:$d, (trunc RegI64:$a))]>; @@ -959,6 +1032,10 @@ def CVT_u64_pred : InstPTX<(outs RegI64:$d), (ins RegPred:$a), "selp.u64\t$d, 1, 0, $a", [(set RegI64:$d, (zext RegPred:$a))]>; +def CVT_u64_u8 + : InstPTX<(outs RegI64:$d), (ins RegI8:$a), "cvt.u64.u8\t$d, $a", + [(set RegI64:$d, (zext RegI8:$a))]>; + def CVT_u64_u16 : InstPTX<(outs RegI64:$d), (ins RegI16:$a), "cvt.u64.u16\t$d, $a", [(set RegI64:$d, (zext RegI16:$a))]>; @@ -967,6 +1044,22 @@ def CVT_u64_u32 : InstPTX<(outs RegI64:$d), (ins RegI32:$a), "cvt.u64.u32\t$d, $a", [(set RegI64:$d, (zext RegI32:$a))]>; +def CVT_u64_preds + : InstPTX<(outs RegI64:$d), (ins RegPred:$a), "selp.u64\t$d, 1, 0, $a", + [(set RegI64:$d, (sext RegPred:$a))]>; + +def CVT_u64_s8 + : InstPTX<(outs RegI64:$d), (ins RegI8:$a), "cvt.u64.s8\t$d, $a", + [(set RegI64:$d, (zext RegI8:$a))]>; + +def CVT_u64_s16 + : InstPTX<(outs RegI64:$d), (ins RegI16:$a), "cvt.u64.s16\t$d, $a", + [(set RegI64:$d, (sext RegI16:$a))]>; + +def CVT_u64_s32 + : InstPTX<(outs RegI64:$d), (ins RegI32:$a), "cvt.u64.s32\t$d, $a", + [(set RegI64:$d, (sext RegI32:$a))]>; + def CVT_u64_f32 : InstPTX<(outs RegI64:$d), (ins RegF32:$a), "cvt.rzi.u64.f32\t$d, $a", [(set RegI64:$d, (fp_to_uint RegF32:$a))]>; @@ -982,6 +1075,10 @@ def CVT_f32_pred "selp.f32\t$d, 0F3F800000, 0F00000000, $a", // 1.0 [(set RegF32:$d, (uint_to_fp RegPred:$a))]>; +def CVT_f32_u8 + : InstPTX<(outs RegF32:$d), (ins RegI8:$a), "cvt.rn.f32.u8\t$d, $a", + [(set RegF32:$d, (uint_to_fp RegI8:$a))]>; + def CVT_f32_u16 : InstPTX<(outs RegF32:$d), (ins RegI16:$a), "cvt.rn.f32.u16\t$d, $a", [(set RegF32:$d, (uint_to_fp RegI16:$a))]>; @@ -1005,6 +1102,10 @@ def CVT_f64_pred "selp.f64\t$d, 0D3F80000000000000, 0D0000000000000000, $a", // 1.0 [(set RegF64:$d, (uint_to_fp RegPred:$a))]>; +def CVT_f64_u8 + : InstPTX<(outs RegF64:$d), (ins RegI8:$a), "cvt.rn.f64.u8\t$d, $a", + [(set RegF64:$d, (uint_to_fp RegI8:$a))]>; + def CVT_f64_u16 : InstPTX<(outs RegF64:$d), (ins RegI16:$a), "cvt.rn.f64.u16\t$d, $a", [(set RegF64:$d, (uint_to_fp RegI16:$a))]>; @@ -1043,6 +1144,8 @@ let isReturn = 1, isTerminator = 1, isBarrier = 1 in { ///===- Spill Instructions ------------------------------------------------===// // Special instructions used for stack spilling +def STACKSTOREI8 : InstPTX<(outs), (ins i32imm:$d, RegI8:$a), + "mov.u8\ts$d, $a", []>; def STACKSTOREI16 : InstPTX<(outs), (ins i32imm:$d, RegI16:$a), "mov.u16\ts$d, $a", []>; def STACKSTOREI32 : InstPTX<(outs), (ins i32imm:$d, RegI32:$a), @@ -1054,6 +1157,8 @@ def STACKSTOREF32 : InstPTX<(outs), (ins i32imm:$d, RegF32:$a), def STACKSTOREF64 : InstPTX<(outs), (ins i32imm:$d, RegF64:$a), "mov.f64\ts$d, $a", []>; +def STACKLOADI8 : InstPTX<(outs), (ins RegI8:$d, i32imm:$a), + "mov.u8\t$d, s$a", []>; def STACKLOADI16 : InstPTX<(outs), (ins RegI16:$d, i32imm:$a), "mov.u16\t$d, s$a", []>; def STACKLOADI32 : InstPTX<(outs), (ins RegI32:$d, i32imm:$a), diff --git a/lib/Target/PTX/PTXRegisterInfo.td b/lib/Target/PTX/PTXRegisterInfo.td index 1313d24..3e7fe56 100644 --- a/lib/Target/PTX/PTXRegisterInfo.td +++ b/lib/Target/PTX/PTXRegisterInfo.td @@ -151,6 +151,137 @@ def P125 : PTXReg<"p125">; def P126 : PTXReg<"p126">; def P127 : PTXReg<"p127">; +///===- 8-Bit Registers --------------------------------------------------===// + +def RQ0 : PTXReg<"rq0">; +def RQ1 : PTXReg<"rq1">; +def RQ2 : PTXReg<"rq2">; +def RQ3 : PTXReg<"rq3">; +def RQ4 : PTXReg<"rq4">; +def RQ5 : PTXReg<"rq5">; +def RQ6 : PTXReg<"rq6">; +def RQ7 : PTXReg<"rq7">; +def RQ8 : PTXReg<"rq8">; +def RQ9 : PTXReg<"rq9">; +def RQ10 : PTXReg<"rq10">; +def RQ11 : PTXReg<"rq11">; +def RQ12 : PTXReg<"rq12">; +def RQ13 : PTXReg<"rq13">; +def RQ14 : PTXReg<"rq14">; +def RQ15 : PTXReg<"rq15">; +def RQ16 : PTXReg<"rq16">; +def RQ17 : PTXReg<"rq17">; +def RQ18 : PTXReg<"rq18">; +def RQ19 : PTXReg<"rq19">; +def RQ20 : PTXReg<"rq20">; +def RQ21 : PTXReg<"rq21">; +def RQ22 : PTXReg<"rq22">; +def RQ23 : PTXReg<"rq23">; +def RQ24 : PTXReg<"rq24">; +def RQ25 : PTXReg<"rq25">; +def RQ26 : PTXReg<"rq26">; +def RQ27 : PTXReg<"rq27">; +def RQ28 : PTXReg<"rq28">; +def RQ29 : PTXReg<"rq29">; +def RQ30 : PTXReg<"rq30">; +def RQ31 : PTXReg<"rq31">; +def RQ32 : PTXReg<"rq32">; +def RQ33 : PTXReg<"rq33">; +def RQ34 : PTXReg<"rq34">; +def RQ35 : PTXReg<"rq35">; +def RQ36 : PTXReg<"rq36">; +def RQ37 : PTXReg<"rq37">; +def RQ38 : PTXReg<"rq38">; +def RQ39 : PTXReg<"rq39">; +def RQ40 : PTXReg<"rq40">; +def RQ41 : PTXReg<"rq41">; +def RQ42 : PTXReg<"rq42">; +def RQ43 : PTXReg<"rq43">; +def RQ44 : PTXReg<"rq44">; +def RQ45 : PTXReg<"rq45">; +def RQ46 : PTXReg<"rq46">; +def RQ47 : PTXReg<"rq47">; +def RQ48 : PTXReg<"rq48">; +def RQ49 : PTXReg<"rq49">; +def RQ50 : PTXReg<"rq50">; +def RQ51 : PTXReg<"rq51">; +def RQ52 : PTXReg<"rq52">; +def RQ53 : PTXReg<"rq53">; +def RQ54 : PTXReg<"rq54">; +def RQ55 : PTXReg<"rq55">; +def RQ56 : PTXReg<"rq56">; +def RQ57 : PTXReg<"rq57">; +def RQ58 : PTXReg<"rq58">; +def RQ59 : PTXReg<"rq59">; +def RQ60 : PTXReg<"rq60">; +def RQ61 : PTXReg<"rq61">; +def RQ62 : PTXReg<"rq62">; +def RQ63 : PTXReg<"rq63">; +def RQ64 : PTXReg<"rq64">; +def RQ65 : PTXReg<"rq65">; +def RQ66 : PTXReg<"rq66">; +def RQ67 : PTXReg<"rq67">; +def RQ68 : PTXReg<"rq68">; +def RQ69 : PTXReg<"rq69">; +def RQ70 : PTXReg<"rq70">; +def RQ71 : PTXReg<"rq71">; +def RQ72 : PTXReg<"rq72">; +def RQ73 : PTXReg<"rq73">; +def RQ74 : PTXReg<"rq74">; +def RQ75 : PTXReg<"rq75">; +def RQ76 : PTXReg<"rq76">; +def RQ77 : PTXReg<"rq77">; +def RQ78 : PTXReg<"rq78">; +def RQ79 : PTXReg<"rq79">; +def RQ80 : PTXReg<"rq80">; +def RQ81 : PTXReg<"rq81">; +def RQ82 : PTXReg<"rq82">; +def RQ83 : PTXReg<"rq83">; +def RQ84 : PTXReg<"rq84">; +def RQ85 : PTXReg<"rq85">; +def RQ86 : PTXReg<"rq86">; +def RQ87 : PTXReg<"rq87">; +def RQ88 : PTXReg<"rq88">; +def RQ89 : PTXReg<"rq89">; +def RQ90 : PTXReg<"rq90">; +def RQ91 : PTXReg<"rq91">; +def RQ92 : PTXReg<"rq92">; +def RQ93 : PTXReg<"rq93">; +def RQ94 : PTXReg<"rq94">; +def RQ95 : PTXReg<"rq95">; +def RQ96 : PTXReg<"rq96">; +def RQ97 : PTXReg<"rq97">; +def RQ98 : PTXReg<"rq98">; +def RQ99 : PTXReg<"rq99">; +def RQ100 : PTXReg<"rq100">; +def RQ101 : PTXReg<"rq101">; +def RQ102 : PTXReg<"rq102">; +def RQ103 : PTXReg<"rq103">; +def RQ104 : PTXReg<"rq104">; +def RQ105 : PTXReg<"rq105">; +def RQ106 : PTXReg<"rq106">; +def RQ107 : PTXReg<"rq107">; +def RQ108 : PTXReg<"rq108">; +def RQ109 : PTXReg<"rq109">; +def RQ110 : PTXReg<"rq110">; +def RQ111 : PTXReg<"rq111">; +def RQ112 : PTXReg<"rq112">; +def RQ113 : PTXReg<"rq113">; +def RQ114 : PTXReg<"rq114">; +def RQ115 : PTXReg<"rq115">; +def RQ116 : PTXReg<"rq116">; +def RQ117 : PTXReg<"rq117">; +def RQ118 : PTXReg<"rq118">; +def RQ119 : PTXReg<"rq119">; +def RQ120 : PTXReg<"rq120">; +def RQ121 : PTXReg<"rq121">; +def RQ122 : PTXReg<"rq122">; +def RQ123 : PTXReg<"rq123">; +def RQ124 : PTXReg<"rq124">; +def RQ125 : PTXReg<"rq125">; +def RQ126 : PTXReg<"rq126">; +def RQ127 : PTXReg<"rq127">; + ///===- 16-Bit Registers --------------------------------------------------===// def RH0 : PTXReg<"rh0">; @@ -548,6 +679,7 @@ def RD127 : PTXReg<"rd127">; // Register classes //===----------------------------------------------------------------------===// def RegPred : RegisterClass<"PTX", [i1], 8, (sequence "P%u", 0, 127)>; +def RegI8 : RegisterClass<"PTX", [i8], 8, (sequence "RQ%u", 0, 127)>; def RegI16 : RegisterClass<"PTX", [i16], 16, (sequence "RH%u", 0, 127)>; def RegI32 : RegisterClass<"PTX", [i32], 32, (sequence "R%u", 0, 127)>; def RegI64 : RegisterClass<"PTX", [i64], 64, (sequence "RD%u", 0, 127)>; diff --git a/lib/Target/PTX/generate-register-td.py b/lib/Target/PTX/generate-register-td.py index 1528690..2402391 100755 --- a/lib/Target/PTX/generate-register-td.py +++ b/lib/Target/PTX/generate-register-td.py @@ -15,15 +15,16 @@ from sys import argv, exit, stdout -if len(argv) != 5: - print('Usage: generate-register-td.py ') +if len(argv) != 6: + print('Usage: generate-register-td.py ') exit(1) try: num_pred = int(argv[1]) - num_16bit = int(argv[2]) - num_32bit = int(argv[3]) - num_64bit = int(argv[4]) + num_8bit = int(argv[2]) + num_16bit = int(argv[3]) + num_32bit = int(argv[4]) + num_64bit = int(argv[5]) except: print('ERROR: Invalid integer parameter') exit(1) @@ -60,6 +61,11 @@ td_file.write('\n///===- Predicate Registers ----------------------------------- for r in range(0, num_pred): td_file.write('def P%d : PTXReg<"p%d">;\n' % (r, r)) +# Print 8-bit registers +td_file.write('\n///===- 8-Bit Registers --------------------------------------------------===//\n\n') +for r in range(0, num_8bit): + td_file.write('def RQ%d : PTXReg<"rq%d">;\n' % (r, r)) + # Print 16-bit registers td_file.write('\n///===- 16-Bit Registers --------------------------------------------------===//\n\n') for r in range(0, num_16bit): @@ -86,6 +92,7 @@ td_file.write(''' # Print register classes td_file.write('def RegPred : RegisterClass<"PTX", [i1], 8, (sequence "P%%u", 0, %d)>;\n' % (num_pred-1)) +td_file.write('def RegI8 : RegisterClass<"PTX", [i8], 8, (sequence "RQ%%u", 0, %d)>;\n' % (num_8bit-1)) td_file.write('def RegI16 : RegisterClass<"PTX", [i16], 16, (sequence "RH%%u", 0, %d)>;\n' % (num_16bit-1)) td_file.write('def RegI32 : RegisterClass<"PTX", [i32], 32, (sequence "R%%u", 0, %d)>;\n' % (num_32bit-1)) td_file.write('def RegI64 : RegisterClass<"PTX", [i64], 64, (sequence "RD%%u", 0, %d)>;\n' % (num_64bit-1)) @@ -101,16 +108,20 @@ td_file = open('PTXCallingConv.td', 'w') # Reserve 10% of the available registers for return values, and the other 90% # for parameters num_ret_pred = int(0.1 * num_pred) +num_ret_8bit = int(0.1 * num_8bit) num_ret_16bit = int(0.1 * num_16bit) num_ret_32bit = int(0.1 * num_32bit) num_ret_64bit = int(0.1 * num_64bit) num_param_pred = num_pred - num_ret_pred +num_param_8bit = num_8bit - num_ret_8bit num_param_16bit = num_16bit - num_ret_16bit num_param_32bit = num_32bit - num_ret_32bit num_param_64bit = num_64bit - num_ret_64bit param_regs_pred = [('P%d' % (i+num_ret_pred)) for i in range(0, num_param_pred)] ret_regs_pred = ['P%d' % i for i in range(0, num_ret_pred)] +param_regs_8bit = [('RQ%d' % (i+num_ret_8bit)) for i in range(0, num_param_8bit)] +ret_regs_8bit = ['RQ%d' % i for i in range(0, num_ret_8bit)] param_regs_16bit = [('RH%d' % (i+num_ret_16bit)) for i in range(0, num_param_16bit)] ret_regs_16bit = ['RH%d' % i for i in range(0, num_ret_16bit)] param_regs_32bit = [('R%d' % (i+num_ret_32bit)) for i in range(0, num_param_32bit)] @@ -120,6 +131,8 @@ ret_regs_64bit = ['RD%d' % i for i in range(0, num_ret_64bit)] param_list_pred = reduce(lambda x, y: '%s, %s' % (x, y), param_regs_pred) ret_list_pred = reduce(lambda x, y: '%s, %s' % (x, y), ret_regs_pred) +param_list_8bit = reduce(lambda x, y: '%s, %s' % (x, y), param_regs_8bit) +ret_list_8bit = reduce(lambda x, y: '%s, %s' % (x, y), ret_regs_8bit) param_list_16bit = reduce(lambda x, y: '%s, %s' % (x, y), param_regs_16bit) ret_list_16bit = reduce(lambda x, y: '%s, %s' % (x, y), ret_regs_16bit) param_list_32bit = reduce(lambda x, y: '%s, %s' % (x, y), param_regs_32bit) @@ -144,6 +157,7 @@ td_file.write(''' // PTX Formal Parameter Calling Convention def CC_PTX : CallingConv<[ CCIfType<[i1], CCAssignToReg<[%s]>>, + CCIfType<[i8], CCAssignToReg<[%s]>>, CCIfType<[i16], CCAssignToReg<[%s]>>, CCIfType<[i32,f32], CCAssignToReg<[%s]>>, CCIfType<[i64,f64], CCAssignToReg<[%s]>> @@ -152,12 +166,13 @@ def CC_PTX : CallingConv<[ // PTX Return Value Calling Convention def RetCC_PTX : CallingConv<[ CCIfType<[i1], CCAssignToReg<[%s]>>, + CCIfType<[i8], CCAssignToReg<[%s]>>, CCIfType<[i16], CCAssignToReg<[%s]>>, CCIfType<[i32,f32], CCAssignToReg<[%s]>>, CCIfType<[i64,f64], CCAssignToReg<[%s]>> ]>; -''' % (param_list_pred, param_list_16bit, param_list_32bit, param_list_64bit, - ret_list_pred, ret_list_16bit, ret_list_32bit, ret_list_64bit)) +''' % (param_list_pred, param_list_8bit, param_list_16bit, param_list_32bit, param_list_64bit, + ret_list_pred, ret_list_8bit, ret_list_16bit, ret_list_32bit, ret_list_64bit)) td_file.close() diff --git a/test/CodeGen/PTX/cvt.ll b/test/CodeGen/PTX/cvt.ll index 18f7ef3..dbabbf8 100644 --- a/test/CodeGen/PTX/cvt.ll +++ b/test/CodeGen/PTX/cvt.ll @@ -3,6 +3,17 @@ ; preds ; (note: we convert back to i32 to return) +define ptx_device i32 @cvt_pred_i8(i8 %x, i1 %y) { +; CHECK: setp.gt.b8 p[[P0:[0-9]+]], rq{{[0-9]+}}, 0 +; CHECK-NEXT: and.pred p0, p[[P0:[0-9]+]], p{{[0-9]+}}; +; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0:[0-9]+]]; +; CHECK-NEXT: ret; + %a = trunc i8 %x to i1 + %b = and i1 %a, %y + %c = zext i1 %b to i32 + ret i32 %c +} + define ptx_device i32 @cvt_pred_i16(i16 %x, i1 %y) { ; CHECK: setp.gt.b16 p[[P0:[0-9]+]], rh{{[0-9]+}}, 0 ; CHECK-NEXT: and.pred p0, p[[P0:[0-9]+]], p{{[0-9]+}}; @@ -58,6 +69,43 @@ define ptx_device i32 @cvt_pred_f64(double %x, i1 %y) { ret i32 %c } +; i8 + +define ptx_device i8 @cvt_i8_preds(i1 %x) { +; CHECK: selp.u8 rq{{[0-9]+}}, 1, 0, p{{[0-9]+}}; +; CHECK-NEXT: ret; + %a = zext i1 %x to i8 + ret i8 %a +} + +define ptx_device i8 @cvt_i8_i32(i32 %x) { +; CHECK: cvt.u8.u32 rq{{[0-9]+}}, r{{[0-9]+}}; +; CHECK-NEXT: ret; + %a = trunc i32 %x to i8 + ret i8 %a +} + +define ptx_device i8 @cvt_i8_i64(i64 %x) { +; CHECK: cvt.u8.u64 rq{{[0-9]+}}, rd{{[0-9]+}}; +; CHECK-NEXT: ret; + %a = trunc i64 %x to i8 + ret i8 %a +} + +define ptx_device i8 @cvt_i8_f32(float %x) { +; CHECK: cvt.rzi.u8.f32 rq{{[0-9]+}}, r{{[0-9]+}}; +; CHECK-NEXT: ret; + %a = fptoui float %x to i8 + ret i8 %a +} + +define ptx_device i8 @cvt_i8_f64(double %x) { +; CHECK: cvt.rzi.u8.f64 rq{{[0-9]+}}, rd{{[0-9]+}}; +; CHECK-NEXT: ret; + %a = fptoui double %x to i8 + ret i8 %a +} + ; i16 define ptx_device i16 @cvt_i16_preds(i1 %x) { @@ -67,6 +115,13 @@ define ptx_device i16 @cvt_i16_preds(i1 %x) { ret i16 %a } +define ptx_device i16 @cvt_i16_i8(i8 %x) { +; CHECK: cvt.u16.u8 rh{{[0-9]+}}, rq{{[0-9]+}}; +; CHECK-NEXT: ret; + %a = zext i8 %x to i16 + ret i16 %a +} + define ptx_device i16 @cvt_i16_i32(i32 %x) { ; CHECK: cvt.u16.u32 rh{{[0-9]+}}, r{{[0-9]+}}; ; CHECK-NEXT: ret; @@ -104,6 +159,13 @@ define ptx_device i32 @cvt_i32_preds(i1 %x) { ret i32 %a } +define ptx_device i32 @cvt_i32_i8(i8 %x) { +; CHECK: cvt.u32.u8 r{{[0-9]+}}, rq{{[0-9]+}}; +; CHECK-NEXT: ret; + %a = zext i8 %x to i32 + ret i32 %a +} + define ptx_device i32 @cvt_i32_i16(i16 %x) { ; CHECK: cvt.u32.u16 r{{[0-9]+}}, rh{{[0-9]+}}; ; CHECK-NEXT: ret; @@ -141,6 +203,13 @@ define ptx_device i64 @cvt_i64_preds(i1 %x) { ret i64 %a } +define ptx_device i64 @cvt_i64_i8(i8 %x) { +; CHECK: cvt.u64.u8 rd{{[0-9]+}}, rq{{[0-9]+}}; +; CHECK-NEXT: ret; + %a = zext i8 %x to i64 + ret i64 %a +} + define ptx_device i64 @cvt_i64_i16(i16 %x) { ; CHECK: cvt.u64.u16 rd{{[0-9]+}}, rh{{[0-9]+}}; ; CHECK-NEXT: ret; @@ -178,6 +247,13 @@ define ptx_device float @cvt_f32_preds(i1 %x) { ret float %a } +define ptx_device float @cvt_f32_i8(i8 %x) { +; CHECK: cvt.rn.f32.u8 r{{[0-9]+}}, rq{{[0-9]+}}; +; CHECK-NEXT: ret; + %a = uitofp i8 %x to float + ret float %a +} + define ptx_device float @cvt_f32_i16(i16 %x) { ; CHECK: cvt.rn.f32.u16 r{{[0-9]+}}, rh{{[0-9]+}}; ; CHECK-NEXT: ret; @@ -215,6 +291,13 @@ define ptx_device double @cvt_f64_preds(i1 %x) { ret double %a } +define ptx_device double @cvt_f64_i8(i8 %x) { +; CHECK: cvt.rn.f64.u8 rd{{[0-9]+}}, rq{{[0-9]+}}; +; CHECK-NEXT: ret; + %a = uitofp i8 %x to double + ret double %a +} + define ptx_device double @cvt_f64_i16(i16 %x) { ; CHECK: cvt.rn.f64.u16 rd{{[0-9]+}}, rh{{[0-9]+}}; ; CHECK-NEXT: ret; diff --git a/test/CodeGen/PTX/ld.ll b/test/CodeGen/PTX/ld.ll index d184d12..951b14b 100644 --- a/test/CodeGen/PTX/ld.ll +++ b/test/CodeGen/PTX/ld.ll @@ -1,5 +1,17 @@ ; RUN: llc < %s -march=ptx32 | FileCheck %s +;CHECK: .extern .global .b8 array_i8[10]; +@array_i8 = external global [10 x i8] + +;CHECK: .extern .const .b8 array_constant_i8[10]; +@array_constant_i8 = external addrspace(1) constant [10 x i8] + +;CHECK: .extern .local .b8 array_local_i8[10]; +@array_local_i8 = external addrspace(2) global [10 x i8] + +;CHECK: .extern .shared .b8 array_shared_i8[10]; +@array_shared_i8 = external addrspace(4) global [10 x i8] + ;CHECK: .extern .global .b8 array_i16[20]; @array_i16 = external global [10 x i16] @@ -60,6 +72,13 @@ ;CHECK: .extern .shared .b8 array_shared_double[80]; @array_shared_double = external addrspace(4) global [10 x double] +define ptx_device i8 @t1_u8(i8* %p) { +entry: +;CHECK: ld.global.u8 rq{{[0-9]+}}, [r{{[0-9]+}}]; +;CHECK-NEXT: ret; + %x = load i8* %p + ret i8 %x +} define ptx_device i16 @t1_u16(i16* %p) { entry: @@ -101,6 +120,15 @@ entry: ret double %x } +define ptx_device i8 @t2_u8(i8* %p) { +entry: +;CHECK: ld.global.u8 rq{{[0-9]+}}, [r{{[0-9]+}}+1]; +;CHECK-NEXT: ret; + %i = getelementptr i8* %p, i32 1 + %x = load i8* %i + ret i8 %x +} + define ptx_device i16 @t2_u16(i16* %p) { entry: ;CHECK: ld.global.u16 rh{{[0-9]+}}, [r{{[0-9]+}}+2]; @@ -146,6 +174,15 @@ entry: ret double %x } +define ptx_device i8 @t3_u8(i8* %p, i32 %q) { +entry: +;CHECK: add.u32 r[[R0:[0-9]+]], r{{[0-9]+}}, r{{[0-9]+}}; +;CHECK-NEXT: ld.global.u8 rq{{[0-9]+}}, [r[[R0]]]; + %i = getelementptr i8* %p, i32 %q + %x = load i8* %i + ret i8 %x +} + define ptx_device i16 @t3_u16(i16* %p, i32 %q) { entry: ;CHECK: shl.b32 r[[R0:[0-9]+]], r{{[0-9]+}}, 1; @@ -196,6 +233,16 @@ entry: ret double %x } +define ptx_device i8 @t4_global_u8() { +entry: +;CHECK: mov.u32 r[[R0:[0-9]+]], array_i8; +;CHECK-NEXT: ld.global.u8 rq{{[0-9]+}}, [r[[R0]]]; +;CHECK-NEXT: ret; + %i = getelementptr [10 x i8]* @array_i8, i32 0, i32 0 + %x = load i8* %i + ret i8 %x +} + define ptx_device i16 @t4_global_u16() { entry: ;CHECK: mov.u32 r[[R0:[0-9]+]], array_i16; @@ -296,6 +343,16 @@ entry: ret double %x } +define ptx_device i8 @t4_local_u8() { +entry: +;CHECK: mov.u32 r[[R0:[0-9]+]], array_local_i8; +;CHECK-NEXT: ld.local.u8 rq{{[0-9]+}}, [r[[R0]]]; +;CHECK-NEXT: ret; + %i = getelementptr [10 x i8] addrspace(2)* @array_local_i8, i32 0, i32 0 + %x = load i8 addrspace(2)* %i + ret i8 %x +} + define ptx_device i16 @t4_local_u16() { entry: ;CHECK: mov.u32 r[[R0:[0-9]+]], array_local_i16; @@ -346,6 +403,16 @@ entry: ret double %x } +define ptx_device i8 @t4_shared_u8() { +entry: +;CHECK: mov.u32 r[[R0:[0-9]+]], array_shared_i8; +;CHECK-NEXT: ld.shared.u8 rq{{[0-9]+}}, [r[[R0]]]; +;CHECK-NEXT: ret; + %i = getelementptr [10 x i8] addrspace(4)* @array_shared_i8, i32 0, i32 0 + %x = load i8 addrspace(4)* %i + ret i8 %x +} + define ptx_device i16 @t4_shared_u16() { entry: ;CHECK: mov.u32 r[[R0:[0-9]+]], array_shared_i16; @@ -396,6 +463,16 @@ entry: ret double %x } +define ptx_device i8 @t5_u8() { +entry: +;CHECK: mov.u32 r[[R0:[0-9]+]], array_i8; +;CHECK-NEXT: ld.global.u8 rq{{[0-9]+}}, [r[[R0]]+1]; +;CHECK-NEXT: ret; + %i = getelementptr [10 x i8]* @array_i8, i32 0, i32 1 + %x = load i8* %i + ret i8 %x +} + define ptx_device i16 @t5_u16() { entry: ;CHECK: mov.u32 r[[R0:[0-9]+]], array_i16; diff --git a/test/CodeGen/PTX/mov.ll b/test/CodeGen/PTX/mov.ll index cce6a5b..b930b4c 100644 --- a/test/CodeGen/PTX/mov.ll +++ b/test/CodeGen/PTX/mov.ll @@ -1,5 +1,11 @@ ; RUN: llc < %s -march=ptx32 | FileCheck %s +define ptx_device i8 @t1_u8() { +; CHECK: mov.u8 rq{{[0-9]+}}, 0; +; CHECK: ret; + ret i8 0 +} + define ptx_device i16 @t1_u16() { ; CHECK: mov.u16 rh{{[0-9]+}}, 0; ; CHECK: ret; @@ -30,6 +36,12 @@ define ptx_device double @t1_f64() { ret double 0.0 } +define ptx_device i8 @t2_u8(i8 %x) { +; CHECK: mov.u8 rq{{[0-9]+}}, rq{{[0-9]+}}; +; CHECK: ret; + ret i8 %x +} + define ptx_device i16 @t2_u16(i16 %x) { ; CHECK: mov.u16 rh{{[0-9]+}}, rh{{[0-9]+}}; ; CHECK: ret; diff --git a/test/CodeGen/PTX/st.ll b/test/CodeGen/PTX/st.ll index b08528e..596d189 100644 --- a/test/CodeGen/PTX/st.ll +++ b/test/CodeGen/PTX/st.ll @@ -1,5 +1,17 @@ ; RUN: llc < %s -march=ptx32 | FileCheck %s +;CHECK: .extern .global .b8 array_i8[10]; +@array_i8 = external global [10 x i8] + +;CHECK: .extern .const .b8 array_constant_i8[10]; +@array_constant_i8 = external addrspace(1) constant [10 x i8] + +;CHECK: .extern .local .b8 array_local_i8[10]; +@array_local_i8 = external addrspace(2) global [10 x i8] + +;CHECK: .extern .shared .b8 array_shared_i8[10]; +@array_shared_i8 = external addrspace(4) global [10 x i8] + ;CHECK: .extern .global .b8 array_i16[20]; @array_i16 = external global [10 x i16] @@ -60,6 +72,13 @@ ;CHECK: .extern .shared .b8 array_shared_double[80]; @array_shared_double = external addrspace(4) global [10 x double] +define ptx_device void @t1_u8(i8* %p, i8 %x) { +entry: +;CHECK: st.global.u8 [r{{[0-9]+}}], rq{{[0-9]+}}; +;CHECK-NEXT: ret; + store i8 %x, i8* %p + ret void +} define ptx_device void @t1_u16(i16* %p, i16 %x) { entry: @@ -101,6 +120,15 @@ entry: ret void } +define ptx_device void @t2_u8(i8* %p, i8 %x) { +entry: +;CHECK: st.global.u8 [r{{[0-9]+}}+1], rq{{[0-9]+}}; +;CHECK-NEXT: ret; + %i = getelementptr i8* %p, i32 1 + store i8 %x, i8* %i + ret void +} + define ptx_device void @t2_u16(i16* %p, i16 %x) { entry: ;CHECK: st.global.u16 [r{{[0-9]+}}+2], rh{{[0-9]+}}; @@ -146,6 +174,16 @@ entry: ret void } +define ptx_device void @t3_u8(i8* %p, i32 %q, i8 %x) { +entry: +;CHECK: add.u32 r[[R0:[0-9]+]], r{{[0-9]+}}, r{{[0-9]+}}; +;CHECK-NEXT: st.global.u8 [r[[R0]]], rq{{[0-9]+}}; +;CHECK-NEXT: ret; + %i = getelementptr i8* %p, i32 %q + store i8 %x, i8* %i + ret void +} + define ptx_device void @t3_u16(i16* %p, i32 %q, i16 %x) { entry: ;CHECK: shl.b32 r[[R0:[0-9]+]], r{{[0-9]+}}, 1; @@ -201,6 +239,16 @@ entry: ret void } +define ptx_device void @t4_global_u8(i8 %x) { +entry: +;CHECK: mov.u32 r[[R0:[0-9]+]], array_i8; +;CHECK-NEXT: st.global.u8 [r[[R0]]], rq{{[0-9]+}}; +;CHECK-NEXT: ret; + %i = getelementptr [10 x i8]* @array_i8, i8 0, i8 0 + store i8 %x, i8* %i + ret void +} + define ptx_device void @t4_global_u16(i16 %x) { entry: ;CHECK: mov.u32 r[[R0:[0-9]+]], array_i16; @@ -251,6 +299,16 @@ entry: ret void } +define ptx_device void @t4_local_u8(i8 %x) { +entry: +;CHECK: mov.u32 r[[R0:[0-9]+]], array_local_i8; +;CHECK-NEXT: st.local.u8 [r[[R0]]], rq{{[0-9]+}}; +;CHECK-NEXT: ret; + %i = getelementptr [10 x i8] addrspace(2)* @array_local_i8, i32 0, i32 0 + store i8 %x, i8 addrspace(2)* %i + ret void +} + define ptx_device void @t4_local_u16(i16 %x) { entry: ;CHECK: mov.u32 r[[R0:[0-9]+]], array_local_i16; @@ -301,6 +359,16 @@ entry: ret void } +define ptx_device void @t4_shared_u8(i8 %x) { +entry: +;CHECK: mov.u32 r[[R0:[0-9]+]], array_shared_i8; +;CHECK-NEXT: st.shared.u8 [r[[R0]]], rq{{[0-9]+}}; +;CHECK-NEXT: ret; + %i = getelementptr [10 x i8] addrspace(4)* @array_shared_i8, i32 0, i32 0 + store i8 %x, i8 addrspace(4)* %i + ret void +} + define ptx_device void @t4_shared_u16(i16 %x) { entry: ;CHECK: mov.u32 r[[R0:[0-9]+]], array_shared_i16; @@ -351,6 +419,16 @@ entry: ret void } +define ptx_device void @t5_u8(i8 %x) { +entry: +;CHECK: mov.u32 r[[R0:[0-9]+]], array_i8; +;CHECK-NEXT: st.global.u8 [r[[R0]]+1], rq{{[0-9]+}}; +;CHECK-NEXT: ret; + %i = getelementptr [10 x i8]* @array_i8, i32 0, i32 1 + store i8 %x, i8* %i + ret void +} + define ptx_device void @t5_u16(i16 %x) { entry: ;CHECK: mov.u32 r[[R0:[0-9]+]], array_i16; -- cgit v1.1 From 32e7abd0804de228c50d90e9ee43568c4316b624 Mon Sep 17 00:00:00 2001 From: Jim Grosbach Date: Fri, 24 Jun 2011 19:43:27 +0000 Subject: tidy up whitespace. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133815 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/MC/MachObjectWriter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/MC/MachObjectWriter.cpp b/lib/MC/MachObjectWriter.cpp index 822546e..e11b9df 100644 --- a/lib/MC/MachObjectWriter.cpp +++ b/lib/MC/MachObjectWriter.cpp @@ -1098,7 +1098,7 @@ bool MachObjectWriter::getARMFixupKindMachOInfo(unsigned Kind, RelocType = unsigned(macho::RIT_ARM_ThumbBranch22Bit); Log2Size = llvm::Log2_32(2); return true; - + case ARM::fixup_t2_uncondbranch: case ARM::fixup_arm_thumb_bl: case ARM::fixup_arm_thumb_blx: -- cgit v1.1 From 8b45456700f1e156b0a14000124f274dfac86f14 Mon Sep 17 00:00:00 2001 From: Jim Grosbach Date: Fri, 24 Jun 2011 20:06:59 +0000 Subject: ARM movw/movt fixups need to mask the high bits. The fixup value comes in as the whole 32-bit value, so for the lo16 fixup, the upper bits need to be masked off. Previously we assumed the masking had already been done and asserted. rdar://9635991 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133818 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMAsmBackend.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/Target/ARM/ARMAsmBackend.cpp b/lib/Target/ARM/ARMAsmBackend.cpp index 79e9897..5e438a9 100644 --- a/lib/Target/ARM/ARMAsmBackend.cpp +++ b/lib/Target/ARM/ARMAsmBackend.cpp @@ -174,7 +174,8 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { Value >>= 16; // Fallthrough case ARM::fixup_t2_movw_lo16: - case ARM::fixup_t2_movt_hi16_pcrel: + case ARM::fixup_t2_movt_hi16_pcrel: //FIXME: Shouldn't this be shifted like + // the other hi16 fixup? case ARM::fixup_t2_movw_lo16_pcrel: { unsigned Hi4 = (Value & 0xF000) >> 12; unsigned i = (Value & 0x800) >> 11; @@ -184,8 +185,10 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { // inst{26} = i; // inst{14-12} = Mid3; // inst{7-0} = Lo8; - assert ((((int64_t)Value) >= -0x8000) && (((int64_t)Value) <= 0x7fff) && - "Out of range pc-relative fixup value!"); + // The value comes in as the whole thing, not just the portion required + // for this fixup, so we need to mask off the bits not handled by this + // portion (lo vs. hi). + Value &= 0xffff; Value = (Hi4 << 16) | (i << 26) | (Mid3 << 12) | (Lo8); uint64_t swapped = (Value & 0xFFFF0000) >> 16; swapped |= (Value & 0x0000FFFF) << 16; -- cgit v1.1 From f5fa52ed064098be7130aa4ec1236037907ce3fa Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Fri, 24 Jun 2011 20:42:09 +0000 Subject: - Add MCRegisterInfo registration machinery. Also added x86 registration routines. - Rename TargetRegisterDesc to MCRegisterDesc. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133820 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/MC/MCRegisterInfo.h | 16 +++++--- include/llvm/Target/TargetRegisterInfo.h | 3 ++ include/llvm/Target/TargetRegistry.h | 60 +++++++++++++++++++++-------- lib/Target/X86/TargetDesc/X86TargetDesc.cpp | 10 +++++ lib/Target/X86/TargetDesc/X86TargetDesc.h | 6 +++ utils/TableGen/RegisterInfoEmitter.cpp | 4 +- 6 files changed, 75 insertions(+), 24 deletions(-) diff --git a/include/llvm/MC/MCRegisterInfo.h b/include/llvm/MC/MCRegisterInfo.h index 30db84b..c2ec08e 100644 --- a/include/llvm/MC/MCRegisterInfo.h +++ b/include/llvm/MC/MCRegisterInfo.h @@ -30,7 +30,7 @@ namespace llvm { /// super-registers of the specific register, e.g. RAX, EAX, are super-registers /// of AX. /// -struct TargetRegisterDesc { +struct MCRegisterDesc { const char *Name; // Printable name for the reg (for debugging) const unsigned *Overlaps; // Overlapping registers, described above const unsigned *SubRegs; // Sub-register set, described above @@ -43,20 +43,26 @@ struct TargetRegisterDesc { /// to this array so that we can turn register number into a register /// descriptor. /// +/// Note this class is designed to be a base class of TargetRegisterInfo, which +/// is the interface used by codegen. However, specific targets *should never* +/// specialize this class. MCRegisterInfo should only contain getters to access +/// TableGen generated physical register data. It must not be extended with +/// virtual methods. +/// class MCRegisterInfo { private: - const TargetRegisterDesc *Desc; // Pointer to the descriptor array + const MCRegisterDesc *Desc; // Pointer to the descriptor array unsigned NumRegs; // Number of entries in the array public: /// InitMCRegisterInfo - Initialize MCRegisterInfo, called by TableGen /// auto-generated routines. *DO NOT USE*. - void InitMCRegisterInfo(const TargetRegisterDesc *D, unsigned NR) { + void InitMCRegisterInfo(const MCRegisterDesc *D, unsigned NR) { Desc = D; NumRegs = NR; } - const TargetRegisterDesc &operator[](unsigned RegNo) const { + const MCRegisterDesc &operator[](unsigned RegNo) const { assert(RegNo < NumRegs && "Attempting to access record for invalid register number!"); return Desc[RegNo]; @@ -65,7 +71,7 @@ public: /// Provide a get method, equivalent to [], but more useful if we have a /// pointer to this object. /// - const TargetRegisterDesc &get(unsigned RegNo) const { + const MCRegisterDesc &get(unsigned RegNo) const { return operator[](RegNo); } diff --git a/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h index d50bfe7..2b7e1f9 100644 --- a/include/llvm/Target/TargetRegisterInfo.h +++ b/include/llvm/Target/TargetRegisterInfo.h @@ -256,6 +256,9 @@ public: bool isAllocatable() const { return Allocatable; } }; +/// TargetRegisterDesc - It's just an alias of MCRegisterDesc. +typedef MCRegisterDesc TargetRegisterDesc; + /// TargetRegisterInfoDesc - Extra information, not in MCRegisterDesc, about /// registers. These are used by codegen, not by MC. struct TargetRegisterInfoDesc { diff --git a/include/llvm/Target/TargetRegistry.h b/include/llvm/Target/TargetRegistry.h index 2e21901..cf33899 100644 --- a/include/llvm/Target/TargetRegistry.h +++ b/include/llvm/Target/TargetRegistry.h @@ -66,8 +66,7 @@ namespace llvm { typedef MCAsmInfo *(*AsmInfoCtorFnTy)(const Target &T, StringRef TT); - typedef MCRegisterInfo *(*RegInfoCtorFnTy)(const Target &T, - StringRef TT); + typedef MCRegisterInfo *(*MCRegInfoCtorFnTy)(void); typedef TargetMachine *(*TargetMachineCtorTy)(const Target &T, const std::string &TT, const std::string &Features); @@ -127,9 +126,9 @@ namespace llvm { /// registered. AsmInfoCtorFnTy AsmInfoCtorFn; - /// RegInfoCtorFn - Constructor function for this target's MCRegisterInfo, + /// MCRegInfoCtorFn - Constructor function for this target's MCRegisterInfo, /// if registered. - RegInfoCtorFnTy RegInfoCtorFn; + MCRegInfoCtorFnTy MCRegInfoCtorFn; /// TargetMachineCtorFn - Construction function for this target's /// TargetMachine, if registered. @@ -240,17 +239,12 @@ namespace llvm { return AsmInfoCtorFn(*this, Triple); } - /// createRegInfo - Create a MCRegisterInfo implementation for the specified - /// target triple. + /// createMCRegInfo - Create a MCRegisterInfo implementation. /// - /// \arg Triple - This argument is used to determine the target machine - /// feature set; it should always be provided. Generally this should be - /// either the target triple from the module, or the target triple of the - /// host if that does not exist. - MCRegisterInfo *createRegInfo(StringRef Triple) const { - if (!RegInfoCtorFn) + MCRegisterInfo *createMCRegInfo() const { + if (!MCRegInfoCtorFn) return 0; - return RegInfoCtorFn(*this, Triple); + return MCRegInfoCtorFn(); } /// createTargetMachine - Create a target specific machine implementation @@ -466,7 +460,7 @@ namespace llvm { T.AsmInfoCtorFn = Fn; } - /// RegisterRegInfo - Register a MCRegisterInfo implementation for the + /// RegisterMCRegInfo - Register a MCRegisterInfo implementation for the /// given target. /// /// Clients are responsible for ensuring that registration doesn't occur @@ -475,10 +469,10 @@ namespace llvm { /// /// @param T - The target being registered. /// @param Fn - A function to construct a MCRegisterInfo for the target. - static void RegisterRegInfo(Target &T, Target::RegInfoCtorFnTy Fn) { + static void RegisterMCRegInfo(Target &T, Target::MCRegInfoCtorFnTy Fn) { // Ignore duplicate registration. - if (!T.RegInfoCtorFn) - T.RegInfoCtorFn = Fn; + if (!T.MCRegInfoCtorFn) + T.MCRegInfoCtorFn = Fn; } /// RegisterTargetMachine - Register a TargetMachine implementation for the @@ -691,6 +685,38 @@ namespace llvm { } }; + /// RegisterMCRegInfo - Helper template for registering a target register info + /// implementation. This invokes the static "Create" method on the class to + /// actually do the construction. Usage: + /// + /// extern "C" void LLVMInitializeFooTarget() { + /// extern Target TheFooTarget; + /// RegisterMCRegInfo X(TheFooTarget); + /// } + template + struct RegisterMCRegInfo { + RegisterMCRegInfo(Target &T) { + TargetRegistry::RegisterMCRegInfo(T, &Allocator); + } + private: + static MCRegisterInfo *Allocator() { + return new MCRegisterInfoImpl(); + } + }; + + /// RegisterMCRegInfoFn - Helper template for registering a target register + /// info implementation. This invokes the specified function to do the + /// construction. Usage: + /// + /// extern "C" void LLVMInitializeFooTarget() { + /// extern Target TheFooTarget; + /// RegisterMCRegInfoFn X(TheFooTarget, TheFunction); + /// } + struct RegisterMCRegInfoFn { + RegisterMCRegInfoFn(Target &T, Target::MCRegInfoCtorFnTy Fn) { + TargetRegistry::RegisterMCRegInfo(T, Fn); + } + }; /// RegisterTargetMachine - Helper template for registering a target machine /// implementation, for use in the target machine initialization diff --git a/lib/Target/X86/TargetDesc/X86TargetDesc.cpp b/lib/Target/X86/TargetDesc/X86TargetDesc.cpp index cf03d48..8d61745 100644 --- a/lib/Target/X86/TargetDesc/X86TargetDesc.cpp +++ b/lib/Target/X86/TargetDesc/X86TargetDesc.cpp @@ -13,6 +13,7 @@ #include "X86TargetDesc.h" #include "llvm/MC/MCRegisterInfo.h" +#include "llvm/Target/TargetRegistry.h" #include "X86GenRegisterDesc.inc" using namespace llvm; @@ -21,3 +22,12 @@ MCRegisterInfo *createX86MCRegisterInfo() { InitX86MCRegisterInfo(X); return X; } + +// Force static initialization. +extern "C" void LLVMInitializeX86MCRegInfo() { + RegisterMCRegInfo X(TheX86_32Target); + RegisterMCRegInfo Y(TheX86_64Target); + + TargetRegistry::RegisterMCRegInfo(TheX86_32Target, createX86MCRegisterInfo); + TargetRegistry::RegisterMCRegInfo(TheX86_64Target, createX86MCRegisterInfo); +} diff --git a/lib/Target/X86/TargetDesc/X86TargetDesc.h b/lib/Target/X86/TargetDesc/X86TargetDesc.h index d08aec7..d31f301 100644 --- a/lib/Target/X86/TargetDesc/X86TargetDesc.h +++ b/lib/Target/X86/TargetDesc/X86TargetDesc.h @@ -11,6 +11,12 @@ // //===----------------------------------------------------------------------===// +namespace llvm { +class Target; + +extern Target TheX86_32Target, TheX86_64Target; +} // End llvm namespace + // Defines symbolic names for X86 registers. This defines a mapping from // register name to register number. // diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp index 5b25f82..6fd8bb4 100644 --- a/utils/TableGen/RegisterInfoEmitter.cpp +++ b/utils/TableGen/RegisterInfoEmitter.cpp @@ -631,7 +631,7 @@ void RegisterInfoEmitter::runDesc(raw_ostream &OS) { const std::string &TargetName = Target.getName(); std::string ClassName = TargetName + "GenMCRegisterInfo"; OS << "struct " << ClassName << " : public MCRegisterInfo {\n" - << " explicit " << ClassName << "(const TargetRegisterDesc *D);\n"; + << " explicit " << ClassName << "(const MCRegisterDesc *D);\n"; OS << "};\n"; OS << "\nnamespace {\n"; @@ -684,7 +684,7 @@ void RegisterInfoEmitter::runDesc(raw_ostream &OS) { OS << "0 };\n"; } - OS << "\n const TargetRegisterDesc " << TargetName + OS << "\n const MCRegisterDesc " << TargetName << "RegDesc[] = { // Descriptors\n"; OS << " { \"NOREG\",\t0,\t0,\t0 },\n"; -- cgit v1.1 From 8594d429e02c688d428036f8563f09572da3fbff Mon Sep 17 00:00:00 2001 From: Devang Patel Date: Fri, 24 Jun 2011 20:46:11 +0000 Subject: Handle debug info for i128 constants. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133821 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CodeGen/MachineInstrBuilder.h | 5 +++ include/llvm/CodeGen/MachineOperand.h | 16 +++++++++ lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 2 ++ lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp | 2 +- lib/CodeGen/AsmPrinter/DwarfCompileUnit.h | 2 +- lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 38 +++++++++++--------- lib/CodeGen/MachineInstr.cpp | 3 ++ lib/CodeGen/SelectionDAG/FastISel.cpp | 11 ++++-- lib/CodeGen/SelectionDAG/InstrEmitter.cpp | 8 ++--- lib/VMCore/AsmWriter.cpp | 55 +++++++++++++++++++++++++++++ lib/VMCore/DebugInfoProbe.cpp | 36 +++++++++++++------ test/CodeGen/Generic/legalize-dbg-value.ll | 25 ------------- test/CodeGen/X86/dbg-i128-const.ll | 26 ++++++++++++++ 13 files changed, 166 insertions(+), 63 deletions(-) delete mode 100644 test/CodeGen/Generic/legalize-dbg-value.ll create mode 100644 test/CodeGen/X86/dbg-i128-const.ll diff --git a/include/llvm/CodeGen/MachineInstrBuilder.h b/include/llvm/CodeGen/MachineInstrBuilder.h index c8183a3..1c48af9 100644 --- a/include/llvm/CodeGen/MachineInstrBuilder.h +++ b/include/llvm/CodeGen/MachineInstrBuilder.h @@ -77,6 +77,11 @@ public: return *this; } + const MachineInstrBuilder &addCImm(const ConstantInt *Val) const { + MI->addOperand(MachineOperand::CreateCImm(Val)); + return *this; + } + const MachineInstrBuilder &addFPImm(const ConstantFP *Val) const { MI->addOperand(MachineOperand::CreateFPImm(Val)); return *this; diff --git a/include/llvm/CodeGen/MachineOperand.h b/include/llvm/CodeGen/MachineOperand.h index 140c6e8..fdef574 100644 --- a/include/llvm/CodeGen/MachineOperand.h +++ b/include/llvm/CodeGen/MachineOperand.h @@ -21,6 +21,7 @@ namespace llvm { class BlockAddress; class ConstantFP; +class ConstantInt; class GlobalValue; class MachineBasicBlock; class MachineInstr; @@ -38,6 +39,7 @@ public: enum MachineOperandType { MO_Register, ///< Register operand. MO_Immediate, ///< Immediate operand + MO_CImmediate, ///< Immediate >64bit operand MO_FPImmediate, ///< Floating-point immediate operand MO_MachineBasicBlock, ///< MachineBasicBlock reference MO_FrameIndex, ///< Abstract Stack Frame Index @@ -111,6 +113,7 @@ private: union { MachineBasicBlock *MBB; // For MO_MachineBasicBlock. const ConstantFP *CFP; // For MO_FPImmediate. + const ConstantInt *CI; // For MO_CImmediate. Integers > 64bit. int64_t ImmVal; // For MO_Immediate. const MDNode *MD; // For MO_Metadata. MCSymbol *Sym; // For MO_MCSymbol @@ -173,6 +176,8 @@ public: bool isReg() const { return OpKind == MO_Register; } /// isImm - Tests if this is a MO_Immediate operand. bool isImm() const { return OpKind == MO_Immediate; } + /// isCImm - Test if t his is a MO_CImmediate operand. + bool isCImm() const { return OpKind == MO_CImmediate; } /// isFPImm - Tests if this is a MO_FPImmediate operand. bool isFPImm() const { return OpKind == MO_FPImmediate; } /// isMBB - Tests if this is a MO_MachineBasicBlock operand. @@ -333,6 +338,11 @@ public: return Contents.ImmVal; } + const ConstantInt *getCImm() const { + assert(isCImm() && "Wrong MachineOperand accessor"); + return Contents.CI; + } + const ConstantFP *getFPImm() const { assert(isFPImm() && "Wrong MachineOperand accessor"); return Contents.CFP; @@ -440,6 +450,12 @@ public: return Op; } + static MachineOperand CreateCImm(const ConstantInt *CI) { + MachineOperand Op(MachineOperand::MO_CImmediate); + Op.Contents.CI = CI; + return Op; + } + static MachineOperand CreateFPImm(const ConstantFP *CFP) { MachineOperand Op(MachineOperand::MO_FPImmediate); Op.Contents.CFP = CFP; diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index edfb307..7f314ee 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -575,6 +575,8 @@ static bool EmitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) { } } else if (MI->getOperand(0).isImm()) { OS << MI->getOperand(0).getImm(); + } else if (MI->getOperand(0).isCImm()) { + MI->getOperand(0).getCImm()->getValue().print(OS, false /*isSigned*/); } else { assert(MI->getOperand(0).isReg() && "Unknown operand type"); if (MI->getOperand(0).getReg() == 0) { diff --git a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp index bff1a35..1fe035e 100644 --- a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -491,7 +491,7 @@ bool CompileUnit::addConstantFPValue(DIE *Die, const MachineOperand &MO) { } /// addConstantValue - Add constant value entry in variable DIE. -bool CompileUnit::addConstantValue(DIE *Die, ConstantInt *CI, +bool CompileUnit::addConstantValue(DIE *Die, const ConstantInt *CI, bool Unsigned) { unsigned CIBitWidth = CI->getBitWidth(); if (CIBitWidth <= 64) { diff --git a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h index 60a9b28..213c7fc 100644 --- a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h +++ b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h @@ -181,7 +181,7 @@ public: /// addConstantValue - Add constant value entry in variable DIE. bool addConstantValue(DIE *Die, const MachineOperand &MO, DIType Ty); - bool addConstantValue(DIE *Die, ConstantInt *CI, bool Unsigned); + bool addConstantValue(DIE *Die, const ConstantInt *CI, bool Unsigned); /// addConstantFPValue - Add constant value entry in variable DIE. bool addConstantFPValue(DIE *Die, const MachineOperand &MO); diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 8845bfa..f85a82d 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -618,6 +618,21 @@ DIE *DwarfDebug::constructInlinedScopeDIE(DbgScope *Scope) { return ScopeDIE; } +/// isUnsignedDIType - Return true if type encoding is unsigned. +static bool isUnsignedDIType(DIType Ty) { + DIDerivedType DTy(Ty); + if (DTy.Verify()) + return isUnsignedDIType(DTy.getTypeDerivedFrom()); + + DIBasicType BTy(Ty); + if (BTy.Verify()) { + unsigned Encoding = BTy.getEncoding(); + if (Encoding == dwarf::DW_ATE_unsigned || + Encoding == dwarf::DW_ATE_unsigned_char) + return true; + } + return false; +} /// constructVariableDIE - Construct a DIE for the given DbgVariable. DIE *DwarfDebug::constructVariableDIE(DbgVariable *DV, DbgScope *Scope) { @@ -718,6 +733,11 @@ DIE *DwarfDebug::constructVariableDIE(DbgVariable *DV, DbgScope *Scope) { else if (DVInsn->getOperand(0).isFPImm()) updated = VariableCU->addConstantFPValue(VariableDie, DVInsn->getOperand(0)); + else if (DVInsn->getOperand(0).isCImm()) + updated = + VariableCU->addConstantValue(VariableDie, + DVInsn->getOperand(0).getCImm(), + isUnsignedDIType(DV->getType())); } else { VariableCU->addVariableAddress(DV, VariableDie, Asm->getDebugValueLocation(DVInsn)); @@ -913,22 +933,6 @@ CompileUnit *DwarfDebug::getCompileUnit(const MDNode *N) const { return I->second; } -/// isUnsignedDIType - Return true if type encoding is unsigned. -static bool isUnsignedDIType(DIType Ty) { - DIDerivedType DTy(Ty); - if (DTy.Verify()) - return isUnsignedDIType(DTy.getTypeDerivedFrom()); - - DIBasicType BTy(Ty); - if (BTy.Verify()) { - unsigned Encoding = BTy.getEncoding(); - if (Encoding == dwarf::DW_ATE_unsigned || - Encoding == dwarf::DW_ATE_unsigned_char) - return true; - } - return false; -} - // Return const exprssion if value is a GEP to access merged global // constant. e.g. // i8* getelementptr ({ i8, i8, i8, i8 }* @_MergedGlobals, i32 0, i32 0) @@ -1017,7 +1021,7 @@ void DwarfDebug::constructGlobalVariableDIE(const MDNode *N) { } else { TheCU->addBlock(VariableDIE, dwarf::DW_AT_location, 0, Block); } - } else if (ConstantInt *CI = + } else if (const ConstantInt *CI = dyn_cast_or_null(GV.getConstant())) TheCU->addConstantValue(VariableDIE, CI, isUnsignedDIType(GTy)); else if (const ConstantExpr *CE = getMergedGlobalExpr(N->getOperand(11))) { diff --git a/lib/CodeGen/MachineInstr.cpp b/lib/CodeGen/MachineInstr.cpp index 36b0b83..e423e3f 100644 --- a/lib/CodeGen/MachineInstr.cpp +++ b/lib/CodeGen/MachineInstr.cpp @@ -267,6 +267,9 @@ void MachineOperand::print(raw_ostream &OS, const TargetMachine *TM) const { case MachineOperand::MO_Immediate: OS << getImm(); break; + case MachineOperand::MO_CImmediate: + getCImm()->getValue().print(OS, false); + break; case MachineOperand::MO_FPImmediate: if (getFPImm()->getType()->isFloatTy()) OS << getFPImm()->getValueAPF().convertToFloat(); diff --git a/lib/CodeGen/SelectionDAG/FastISel.cpp b/lib/CodeGen/SelectionDAG/FastISel.cpp index 797f174..8ae75f5 100644 --- a/lib/CodeGen/SelectionDAG/FastISel.cpp +++ b/lib/CodeGen/SelectionDAG/FastISel.cpp @@ -556,9 +556,14 @@ bool FastISel::SelectCall(const User *I) { .addReg(0U).addImm(DI->getOffset()) .addMetadata(DI->getVariable()); } else if (const ConstantInt *CI = dyn_cast(V)) { - BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II) - .addImm(CI->getZExtValue()).addImm(DI->getOffset()) - .addMetadata(DI->getVariable()); + if (CI->getBitWidth() > 64) + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II) + .addCImm(CI).addImm(DI->getOffset()) + .addMetadata(DI->getVariable()); + else + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II) + .addImm(CI->getZExtValue()).addImm(DI->getOffset()) + .addMetadata(DI->getVariable()); } else if (const ConstantFP *CF = dyn_cast(V)) { BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II) .addFPImm(CF).addImm(DI->getOffset()) diff --git a/lib/CodeGen/SelectionDAG/InstrEmitter.cpp b/lib/CodeGen/SelectionDAG/InstrEmitter.cpp index 2a65d65..3c6a46e 100644 --- a/lib/CodeGen/SelectionDAG/InstrEmitter.cpp +++ b/lib/CodeGen/SelectionDAG/InstrEmitter.cpp @@ -616,12 +616,8 @@ InstrEmitter::EmitDbgValue(SDDbgValue *SD, } else if (SD->getKind() == SDDbgValue::CONST) { const Value *V = SD->getConst(); if (const ConstantInt *CI = dyn_cast(V)) { - // FIXME: SDDbgValue constants aren't updated with legalization, so it's - // possible to have i128 constants in them at this point. Dwarf writer - // does not handle i128 constants at the moment so, as a crude workaround, - // just drop the debug info if this happens. - if (!CI->getValue().isSignedIntN(64)) - MIB.addReg(0U); + if (CI->getBitWidth() > 64) + MIB.addCImm(CI); else MIB.addImm(CI->getSExtValue()); } else if (const ConstantFP *CF = dyn_cast(V)) { diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp index 496f500..fff4867 100644 --- a/lib/VMCore/AsmWriter.cpp +++ b/lib/VMCore/AsmWriter.cpp @@ -32,6 +32,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/CFG.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/ErrorHandling.h" @@ -41,6 +42,11 @@ #include using namespace llvm; +static cl::opt +EnableDebugInfoComment("enable-debug-info-comment", cl::Hidden, + cl::desc("Enable debug info comments")); + + // Make virtual table appear in this compilation unit. AssemblyAnnotationWriter::~AssemblyAnnotationWriter() {} @@ -1761,6 +1767,18 @@ void AssemblyWriter::printBasicBlock(const BasicBlock *BB) { if (AnnotationWriter) AnnotationWriter->emitBasicBlockEndAnnot(BB, Out); } +/// printDebugLoc - Print DebugLoc. +static void printDebugLoc(const DebugLoc &DL, formatted_raw_ostream &OS) { + OS << DL.getLine() << ":" << DL.getCol(); + if (MDNode *N = DL.getInlinedAt(getGlobalContext())) { + DebugLoc IDL = DebugLoc::getFromDILocation(N); + if (!IDL.isUnknown()) { + OS << "@"; + printDebugLoc(IDL,OS); + } + } +} + /// printInfoComment - Print a little comment after the instruction indicating /// which slot it occupies. /// @@ -1768,6 +1786,43 @@ void AssemblyWriter::printInfoComment(const Value &V) { if (AnnotationWriter) { AnnotationWriter->printInfoComment(V, Out); return; + } else if (EnableDebugInfoComment) { + bool Padded = false; + if (const Instruction *I = dyn_cast(&V)) { + const DebugLoc &DL = I->getDebugLoc(); + if (!DL.isUnknown()) { + if (!Padded) { + Out.PadToColumn(50); + Padded = true; + Out << ";"; + } + Out << " [debug line = "; + printDebugLoc(DL,Out); + Out << "]"; + } + if (const DbgDeclareInst *DDI = dyn_cast(I)) { + const MDNode *Var = DDI->getVariable(); + if (!Padded) { + Out.PadToColumn(50); + Padded = true; + Out << ";"; + } + if (Var && Var->getNumOperands() >= 2) + if (MDString *MDS = dyn_cast_or_null(Var->getOperand(2))) + Out << " [debug variable = " << MDS->getString() << "]"; + } + else if (const DbgValueInst *DVI = dyn_cast(I)) { + const MDNode *Var = DVI->getVariable(); + if (!Padded) { + Out.PadToColumn(50); + Padded = true; + Out << ";"; + } + if (Var && Var->getNumOperands() >= 2) + if (MDString *MDS = dyn_cast_or_null(Var->getOperand(2))) + Out << " [debug variable = " << MDS->getString() << "]"; + } + } } } diff --git a/lib/VMCore/DebugInfoProbe.cpp b/lib/VMCore/DebugInfoProbe.cpp index d1275ff..382c297 100644 --- a/lib/VMCore/DebugInfoProbe.cpp +++ b/lib/VMCore/DebugInfoProbe.cpp @@ -53,6 +53,7 @@ namespace llvm { Function *TheFn; std::set DbgVariables; std::set MissingDebugLoc; + std::set LineNos; }; } @@ -66,14 +67,19 @@ void DebugInfoProbeImpl::initialize(StringRef PName, Function &F) { DbgVariables.clear(); MissingDebugLoc.clear(); + LineNos.clear(); TheFn = &F; for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI) for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE; ++BI) { - if (!isa(BI) && BI->getDebugLoc().isUnknown()) - MissingDebugLoc.insert(BI); - if (!isa(BI)) continue; + DebugLoc DL = BI->getDebugLoc(); + if (DL.isUnknown()) { + if (!isa(BI)) + MissingDebugLoc.insert(BI); + } else + LineNos.insert(DL.getLine()); + if (!isa(BI)) continue; Value *Addr = NULL; MDNode *Node = NULL; if (DbgDeclareInst *DDI = dyn_cast(BI)) { @@ -114,16 +120,20 @@ void DebugInfoProbeImpl::finalize(Function &F) { assert (TheFn == &F && "Invalid function to measure!"); std::setDbgVariables2; + std::setLineNos2; for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI) for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE; ++BI) { - if (!isa(BI) && BI->getDebugLoc().isUnknown() && - MissingDebugLoc.count(BI) == 0) { - ++NumDbgLineLost; - DEBUG(dbgs() << "DebugInfoProbe (" << PassName << "): --- "); - DEBUG(BI->print(dbgs())); - DEBUG(dbgs() << "\n"); - } + DebugLoc DL = BI->getDebugLoc(); + if (DL.isUnknown()) { + if (!isa(BI) && MissingDebugLoc.count(BI) == 0) { + ++NumDbgLineLost; + DEBUG(dbgs() << "DebugInfoProbe (" << PassName << "): --- "); + DEBUG(BI->print(dbgs())); + DEBUG(dbgs() << "\n"); + } + } else + LineNos2.insert(DL.getLine()); if (!isa(BI)) continue; Value *Addr = NULL; MDNode *Node = NULL; @@ -138,6 +148,12 @@ void DebugInfoProbeImpl::finalize(Function &F) { DbgVariables2.insert(Node); } + for (std::set::iterator I = LineNos.begin(), + E = LineNos.end(); I != E; ++I) { + unsigned LNO = *I; + if (LineNos2.count(LNO) == 0) + DEBUG(dbgs() << "DebugInfoProbe dropping line number " << LNO << "\n"); + } for (std::set::iterator I = DbgVariables.begin(), E = DbgVariables.end(); I != E; ++I) { if (DbgVariables2.count(*I) == 0 && (*I)->getNumOperands() >= 2) { diff --git a/test/CodeGen/Generic/legalize-dbg-value.ll b/test/CodeGen/Generic/legalize-dbg-value.ll deleted file mode 100644 index b71aa8a..0000000 --- a/test/CodeGen/Generic/legalize-dbg-value.ll +++ /dev/null @@ -1,25 +0,0 @@ -; RUN: llc < %s -o /dev/null - -; llvm.dbg.value instructions can have types which are not legal for the -; target. CodeGen should handle this. - -define i128 @__mulvti3(i128 %a, i128 %b) nounwind { -entry: - tail call void @llvm.dbg.value(metadata !0, i64 0, metadata !1), !dbg !11 - unreachable -} - -declare void @llvm.dbg.value(metadata, i64, metadata) nounwind readnone - -!0 = metadata !{i128 170141183460469231731687303715884105727} -!1 = metadata !{i32 524544, metadata !2, metadata !"MAX", metadata !4, i32 29, metadata !8} ; [ DW_TAG_auto_variable ] -!2 = metadata !{i32 524299, metadata !3, i32 26, i32 0} ; [ DW_TAG_lexical_block ] -!3 = metadata !{i32 524334, i32 0, metadata !4, metadata !"__mulvti3", metadata !"__mulvti3", metadata !"__mulvti3", metadata !4, i32 26, metadata !6, i1 false, i1 true, i32 0, i32 0, null, i1 false} ; [ DW_TAG_subprogram ] -!4 = metadata !{i32 524329, metadata !"mulvti3.c", metadata !"/Volumes/Sandbox/llvm/swb/Libcompiler_rt-6.roots/Libcompiler_rt-6/lib", metadata !5} ; [ DW_TAG_file_type ] -!5 = metadata !{i32 524305, i32 0, i32 1, metadata !"mulvti3.c", metadata !"/Volumes/Sandbox/llvm/swb/Libcompiler_rt-6.roots/Libcompiler_rt-6/lib", metadata !"4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2328)", i1 true, i1 true, metadata !"", i32 0} ; [ DW_TAG_compile_unit ] -!6 = metadata !{i32 524309, metadata !4, metadata !"", metadata !4, i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !7, i32 0, null} ; [ DW_TAG_subroutine_type ] -!7 = metadata !{metadata !8, metadata !8, metadata !8} -!8 = metadata !{i32 524310, metadata !4, metadata !"ti_int", metadata !9, i32 78, i64 0, i64 0, i64 0, i32 0, metadata !10} ; [ DW_TAG_typedef ] -!9 = metadata !{i32 524329, metadata !"int_lib.h", metadata !"/Volumes/Sandbox/llvm/swb/Libcompiler_rt-6.roots/Libcompiler_rt-6/lib", metadata !5} ; [ DW_TAG_file_type ] -!10 = metadata !{i32 524324, metadata !4, metadata !"", metadata !4, i32 0, i64 128, i64 128, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] -!11 = metadata !{i32 29, i32 0, metadata !2, null} diff --git a/test/CodeGen/X86/dbg-i128-const.ll b/test/CodeGen/X86/dbg-i128-const.ll new file mode 100644 index 0000000..fb83fca --- /dev/null +++ b/test/CodeGen/X86/dbg-i128-const.ll @@ -0,0 +1,26 @@ +; RUN: llc < %s | FileCheck %s + +; CHECK: DW_AT_const_value +; CHECK-NEXT: 42 + +define i128 @__foo(i128 %a, i128 %b) nounwind { +entry: + tail call void @llvm.dbg.value(metadata !0, i64 0, metadata !1), !dbg !11 + %add = add i128 %a, %b, !dbg !11 + ret i128 %add, !dbg !11 +} + +declare void @llvm.dbg.value(metadata, i64, metadata) nounwind readnone + +!0 = metadata !{i128 42 } +!1 = metadata !{i32 524544, metadata !2, metadata !"MAX", metadata !4, i32 29, metadata !8} ; [ DW_TAG_auto_variable ] +!2 = metadata !{i32 524299, metadata !3, i32 26, i32 0} ; [ DW_TAG_lexical_block ] +!3 = metadata !{i32 524334, i32 0, metadata !4, metadata !"__foo", metadata !"__foo", metadata !"__foo", metadata !4, i32 26, metadata !6, i1 false, i1 true, i32 0, i32 0, null, i1 false} ; [ DW_TAG_subprogram ] +!4 = metadata !{i32 524329, metadata !"foo.c", metadata !"/tmp", metadata !5} ; [ DW_TAG_file_type ] +!5 = metadata !{i32 524305, i32 0, i32 1, metadata !"foo.c", metadata !"/tmp", metadata !"clang", i1 true, i1 true, metadata !"", i32 0} ; [ DW_TAG_compile_unit ] +!6 = metadata !{i32 524309, metadata !4, metadata !"", metadata !4, i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !7, i32 0, null} ; [ DW_TAG_subroutine_type ] +!7 = metadata !{metadata !8, metadata !8, metadata !8} +!8 = metadata !{i32 524310, metadata !4, metadata !"ti_int", metadata !9, i32 78, i64 0, i64 0, i64 0, i32 0, metadata !10} ; [ DW_TAG_typedef ] +!9 = metadata !{i32 524329, metadata !"myint.h", metadata !"/tmp", metadata !5} ; [ DW_TAG_file_type ] +!10 = metadata !{i32 524324, metadata !4, metadata !"", metadata !4, i32 0, i64 128, i64 128, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] +!11 = metadata !{i32 29, i32 0, metadata !2, null} -- cgit v1.1 From 0f03782d16002147608c14b34eb2a37f4881b532 Mon Sep 17 00:00:00 2001 From: Devang Patel Date: Fri, 24 Jun 2011 20:48:14 +0000 Subject: Revert unintentional check-in. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133822 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/VMCore/AsmWriter.cpp | 55 ------------------------------------------- lib/VMCore/DebugInfoProbe.cpp | 36 ++++++++-------------------- 2 files changed, 10 insertions(+), 81 deletions(-) diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp index fff4867..496f500 100644 --- a/lib/VMCore/AsmWriter.cpp +++ b/lib/VMCore/AsmWriter.cpp @@ -32,7 +32,6 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/CFG.h" -#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/ErrorHandling.h" @@ -42,11 +41,6 @@ #include using namespace llvm; -static cl::opt -EnableDebugInfoComment("enable-debug-info-comment", cl::Hidden, - cl::desc("Enable debug info comments")); - - // Make virtual table appear in this compilation unit. AssemblyAnnotationWriter::~AssemblyAnnotationWriter() {} @@ -1767,18 +1761,6 @@ void AssemblyWriter::printBasicBlock(const BasicBlock *BB) { if (AnnotationWriter) AnnotationWriter->emitBasicBlockEndAnnot(BB, Out); } -/// printDebugLoc - Print DebugLoc. -static void printDebugLoc(const DebugLoc &DL, formatted_raw_ostream &OS) { - OS << DL.getLine() << ":" << DL.getCol(); - if (MDNode *N = DL.getInlinedAt(getGlobalContext())) { - DebugLoc IDL = DebugLoc::getFromDILocation(N); - if (!IDL.isUnknown()) { - OS << "@"; - printDebugLoc(IDL,OS); - } - } -} - /// printInfoComment - Print a little comment after the instruction indicating /// which slot it occupies. /// @@ -1786,43 +1768,6 @@ void AssemblyWriter::printInfoComment(const Value &V) { if (AnnotationWriter) { AnnotationWriter->printInfoComment(V, Out); return; - } else if (EnableDebugInfoComment) { - bool Padded = false; - if (const Instruction *I = dyn_cast(&V)) { - const DebugLoc &DL = I->getDebugLoc(); - if (!DL.isUnknown()) { - if (!Padded) { - Out.PadToColumn(50); - Padded = true; - Out << ";"; - } - Out << " [debug line = "; - printDebugLoc(DL,Out); - Out << "]"; - } - if (const DbgDeclareInst *DDI = dyn_cast(I)) { - const MDNode *Var = DDI->getVariable(); - if (!Padded) { - Out.PadToColumn(50); - Padded = true; - Out << ";"; - } - if (Var && Var->getNumOperands() >= 2) - if (MDString *MDS = dyn_cast_or_null(Var->getOperand(2))) - Out << " [debug variable = " << MDS->getString() << "]"; - } - else if (const DbgValueInst *DVI = dyn_cast(I)) { - const MDNode *Var = DVI->getVariable(); - if (!Padded) { - Out.PadToColumn(50); - Padded = true; - Out << ";"; - } - if (Var && Var->getNumOperands() >= 2) - if (MDString *MDS = dyn_cast_or_null(Var->getOperand(2))) - Out << " [debug variable = " << MDS->getString() << "]"; - } - } } } diff --git a/lib/VMCore/DebugInfoProbe.cpp b/lib/VMCore/DebugInfoProbe.cpp index 382c297..d1275ff 100644 --- a/lib/VMCore/DebugInfoProbe.cpp +++ b/lib/VMCore/DebugInfoProbe.cpp @@ -53,7 +53,6 @@ namespace llvm { Function *TheFn; std::set DbgVariables; std::set MissingDebugLoc; - std::set LineNos; }; } @@ -67,19 +66,14 @@ void DebugInfoProbeImpl::initialize(StringRef PName, Function &F) { DbgVariables.clear(); MissingDebugLoc.clear(); - LineNos.clear(); TheFn = &F; for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI) for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE; ++BI) { - DebugLoc DL = BI->getDebugLoc(); - if (DL.isUnknown()) { - if (!isa(BI)) - MissingDebugLoc.insert(BI); - } else - LineNos.insert(DL.getLine()); - if (!isa(BI)) continue; + if (!isa(BI) && BI->getDebugLoc().isUnknown()) + MissingDebugLoc.insert(BI); + if (!isa(BI)) continue; Value *Addr = NULL; MDNode *Node = NULL; if (DbgDeclareInst *DDI = dyn_cast(BI)) { @@ -120,20 +114,16 @@ void DebugInfoProbeImpl::finalize(Function &F) { assert (TheFn == &F && "Invalid function to measure!"); std::setDbgVariables2; - std::setLineNos2; for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI) for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE; ++BI) { - DebugLoc DL = BI->getDebugLoc(); - if (DL.isUnknown()) { - if (!isa(BI) && MissingDebugLoc.count(BI) == 0) { - ++NumDbgLineLost; - DEBUG(dbgs() << "DebugInfoProbe (" << PassName << "): --- "); - DEBUG(BI->print(dbgs())); - DEBUG(dbgs() << "\n"); - } - } else - LineNos2.insert(DL.getLine()); + if (!isa(BI) && BI->getDebugLoc().isUnknown() && + MissingDebugLoc.count(BI) == 0) { + ++NumDbgLineLost; + DEBUG(dbgs() << "DebugInfoProbe (" << PassName << "): --- "); + DEBUG(BI->print(dbgs())); + DEBUG(dbgs() << "\n"); + } if (!isa(BI)) continue; Value *Addr = NULL; MDNode *Node = NULL; @@ -148,12 +138,6 @@ void DebugInfoProbeImpl::finalize(Function &F) { DbgVariables2.insert(Node); } - for (std::set::iterator I = LineNos.begin(), - E = LineNos.end(); I != E; ++I) { - unsigned LNO = *I; - if (LineNos2.count(LNO) == 0) - DEBUG(dbgs() << "DebugInfoProbe dropping line number " << LNO << "\n"); - } for (std::set::iterator I = DbgVariables.begin(), E = DbgVariables.end(); I != E; ++I) { if (DbgVariables2.count(*I) == 0 && (*I)->getNumOperands() >= 2) { -- cgit v1.1 From 56fc6420000876460e8c89c0e7c0ae83ebb5ccf0 Mon Sep 17 00:00:00 2001 From: Jim Grosbach Date: Fri, 24 Jun 2011 20:59:01 +0000 Subject: Testcase for r133818 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133823 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/MC/MachO/thumb2-movt-fixup.s | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 test/MC/MachO/thumb2-movt-fixup.s diff --git a/test/MC/MachO/thumb2-movt-fixup.s b/test/MC/MachO/thumb2-movt-fixup.s new file mode 100644 index 0000000..ddd95b5 --- /dev/null +++ b/test/MC/MachO/thumb2-movt-fixup.s @@ -0,0 +1,17 @@ +@ RUN: llvm-mc -mcpu=cortex-a8 -triple thumbv7-apple-darwin10 -filetype=obj -o - < %s | macho-dump | FileCheck %s + +_fred: + movt r3, :upper16:(_wilma-(LPC0_0+4)) +LPC0_0: + +_wilma: + .long 0 + +@ CHECK: ('_relocations', [ +@ CHECK: # Relocation 0 +@ CHECK: (('word-0', 0xb9000000), +@ CHECK: ('word-1', 0x4)), +@ CHECK: # Relocation 1 +@ CHECK: (('word-0', 0xb100fffc), +@ CHECK: ('word-1', 0x4)), + -- cgit v1.1 From 2416da36ace2130607c652a94b814de7e724efeb Mon Sep 17 00:00:00 2001 From: Chad Rosier Date: Fri, 24 Jun 2011 21:15:36 +0000 Subject: Hoist simple check above more complex checking to avoid unnecessary overheads. No functional change intended. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133824 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86ISelLowering.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 13bef08..6c606be 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -2556,6 +2556,11 @@ X86TargetLowering::IsEligibleForTailCallOptimization(SDValue Callee, if (isCalleeStructRet || isCallerStructRet) return false; + // An stdcall caller is expected to clean up its arguments; the callee + // isn't going to do that. + if (!CCMatch && CallerCC==CallingConv::X86_StdCall) + return false; + // Do not sibcall optimize vararg calls unless all arguments are passed via // registers. if (isVarArg && !Outs.empty()) { @@ -2692,11 +2697,6 @@ X86TargetLowering::IsEligibleForTailCallOptimization(SDValue Callee, } } - // An stdcall caller is expected to clean up its arguments; the callee - // isn't going to do that. - if (!CCMatch && CallerCC==CallingConv::X86_StdCall) - return false; - return true; } -- cgit v1.1 From e9e0e3aeafa32b3a8ba6414053cf90a82c6b2d1e Mon Sep 17 00:00:00 2001 From: Bob Wilson Date: Fri, 24 Jun 2011 21:32:40 +0000 Subject: Shorten some ARM builtin names by removing unnecessary "neon" prefix. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133825 91177308-0d34-0410-b5e6-96231b3b80d8 --- utils/TableGen/NeonEmitter.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/utils/TableGen/NeonEmitter.cpp b/utils/TableGen/NeonEmitter.cpp index ef97744..431f531 100644 --- a/utils/TableGen/NeonEmitter.cpp +++ b/utils/TableGen/NeonEmitter.cpp @@ -889,7 +889,7 @@ static unsigned GetNeonEnum(const std::string &proto, StringRef typestr) { return ret; } -// Generate the definition for this intrinsic, e.g. __builtin_neon_cls(a) +// Generate the definition for this intrinsic. static std::string GenBuiltin(const std::string &name, const std::string &proto, StringRef typestr, ClassKind ck) { std::string s; @@ -923,7 +923,7 @@ static std::string GenBuiltin(const std::string &name, const std::string &proto, bool splat = proto.find('a') != std::string::npos; - s += "__builtin_neon_"; + s += "__builtin_"; if (splat) { // Call the non-splat builtin: chop off the "_n" suffix from the name. std::string vname(name, 0, name.size()-2); @@ -1009,7 +1009,7 @@ static std::string GenBuiltin(const std::string &name, const std::string &proto, static std::string GenBuiltinDef(const std::string &name, const std::string &proto, StringRef typestr, ClassKind ck) { - std::string s("BUILTIN(__builtin_neon_"); + std::string s("BUILTIN(__builtin_"); // If all types are the same size, bitcasting the args will take care // of arg checking. The actual signedness etc. will be taken care of with @@ -1354,11 +1354,11 @@ void NeonEmitter::runHeader(raw_ostream &OS) { } } if (mask) - OS << "case ARM::BI__builtin_neon_" + OS << "case ARM::BI__builtin_" << MangleName(name, TypeVec[si], ClassB) << ": mask = " << "0x" << utohexstr(mask) << "; break;\n"; if (qmask) - OS << "case ARM::BI__builtin_neon_" + OS << "case ARM::BI__builtin_" << MangleName(name, TypeVec[qi], ClassB) << ": mask = " << "0x" << utohexstr(qmask) << "; break;\n"; } @@ -1446,7 +1446,7 @@ void NeonEmitter::runHeader(raw_ostream &OS) { case 'i': ie = ii + 1; break; } } - OS << "case ARM::BI__builtin_neon_" << MangleName(name, TypeVec[ti], ck) + OS << "case ARM::BI__builtin_" << MangleName(name, TypeVec[ti], ck) << ": i = " << immidx << "; " << rangestr << "; break;\n"; } } -- cgit v1.1 From fa3f9c001fe771af7dfcd7663b9d5dc345649d43 Mon Sep 17 00:00:00 2001 From: Devang Patel Date: Fri, 24 Jun 2011 22:00:39 +0000 Subject: Fix struct member's scope. Patch by Xi Wang. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133828 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Analysis/DIBuilder.h | 3 ++- lib/Analysis/DIBuilder.cpp | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/include/llvm/Analysis/DIBuilder.h b/include/llvm/Analysis/DIBuilder.h index 96c6587..a706cc8 100644 --- a/include/llvm/Analysis/DIBuilder.h +++ b/include/llvm/Analysis/DIBuilder.h @@ -135,6 +135,7 @@ namespace llvm { unsigned Flags); /// createMemberType - Create debugging information entry for a member. + /// @param Scope Member scope. /// @param Name Member name. /// @param File File where this member is defined. /// @param LineNo Line number. @@ -143,7 +144,7 @@ namespace llvm { /// @param OffsetInBits Member offset. /// @param Flags Flags to encode member attribute, e.g. private /// @param Ty Parent type. - DIType createMemberType(StringRef Name, DIFile File, + DIType createMemberType(DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNo, uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, DIType Ty); diff --git a/lib/Analysis/DIBuilder.cpp b/lib/Analysis/DIBuilder.cpp index ef5d03a..6a02535 100644 --- a/lib/Analysis/DIBuilder.cpp +++ b/lib/Analysis/DIBuilder.cpp @@ -219,7 +219,7 @@ DIType DIBuilder::createInheritance(DIType Ty, DIType BaseTy, } /// createMemberType - Create debugging information entry for a member. -DIType DIBuilder::createMemberType(StringRef Name, +DIType DIBuilder::createMemberType(DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, @@ -227,7 +227,7 @@ DIType DIBuilder::createMemberType(StringRef Name, // TAG_member is encoded in DIDerivedType format. Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_member), - File, // Or TheCU ? Ty ? + Scope, MDString::get(VMContext, Name), File, ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), -- cgit v1.1 From 1189027f9de5c3d5a6c884fe3a15571891295264 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Fri, 24 Jun 2011 22:01:28 +0000 Subject: Fix cmake build. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133830 91177308-0d34-0410-b5e6-96231b3b80d8 --- cmake/modules/LLVMLibDeps.cmake | 2 +- lib/Target/XCore/CMakeLists.txt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/cmake/modules/LLVMLibDeps.cmake b/cmake/modules/LLVMLibDeps.cmake index 509ac52..f9e2998 100644 --- a/cmake/modules/LLVMLibDeps.cmake +++ b/cmake/modules/LLVMLibDeps.cmake @@ -42,7 +42,7 @@ set(MSVC_LIB_DEPS_LLVMMSP430Info LLVMMC LLVMSupport) set(MSVC_LIB_DEPS_LLVMMipsCodeGen LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMMipsInfo LLVMSelectionDAG LLVMSupport LLVMTarget) set(MSVC_LIB_DEPS_LLVMMipsInfo LLVMMC LLVMSupport) set(MSVC_LIB_DEPS_LLVMObject LLVMSupport) -set(MSVC_LIB_DEPS_LLVMPTXCodeGen LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMPTXInfo LLVMSelectionDAG LLVMSupport LLVMTarget) +set(MSVC_LIB_DEPS_LLVMPTXCodeGen LLVMAnalysis LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMPTXInfo LLVMSelectionDAG LLVMSupport LLVMTarget) set(MSVC_LIB_DEPS_LLVMPTXInfo LLVMMC LLVMSupport) set(MSVC_LIB_DEPS_LLVMPowerPCAsmPrinter LLVMMC LLVMSupport) set(MSVC_LIB_DEPS_LLVMPowerPCCodeGen LLVMAnalysis LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMPowerPCAsmPrinter LLVMPowerPCInfo LLVMSelectionDAG LLVMSupport LLVMTarget) diff --git a/lib/Target/XCore/CMakeLists.txt b/lib/Target/XCore/CMakeLists.txt index 1ed1538..959e9a1 100644 --- a/lib/Target/XCore/CMakeLists.txt +++ b/lib/Target/XCore/CMakeLists.txt @@ -1,5 +1,6 @@ set(LLVM_TARGET_DEFINITIONS XCore.td) +tablegen(XCoreGenRegisterNames.inc -gen-register-enums) tablegen(XCoreGenRegisterDesc.inc -gen-register-desc) tablegen(XCoreGenRegisterInfo.h.inc -gen-register-info-header) tablegen(XCoreGenRegisterInfo.inc -gen-register-info) -- cgit v1.1 From 9c99cfef93c9211a52d4b556e6ef852e826c4d96 Mon Sep 17 00:00:00 2001 From: Bob Wilson Date: Fri, 24 Jun 2011 22:13:17 +0000 Subject: Revert "Shorten some ARM builtin names by removing unnecessary "neon" prefix." Sorry, this was a bad idea. Within clang these builtins are in a separate "ARM" namespace, but the actual builtin names should clearly distinguish that they are target specific. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133832 91177308-0d34-0410-b5e6-96231b3b80d8 --- utils/TableGen/NeonEmitter.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/utils/TableGen/NeonEmitter.cpp b/utils/TableGen/NeonEmitter.cpp index 431f531..ef97744 100644 --- a/utils/TableGen/NeonEmitter.cpp +++ b/utils/TableGen/NeonEmitter.cpp @@ -889,7 +889,7 @@ static unsigned GetNeonEnum(const std::string &proto, StringRef typestr) { return ret; } -// Generate the definition for this intrinsic. +// Generate the definition for this intrinsic, e.g. __builtin_neon_cls(a) static std::string GenBuiltin(const std::string &name, const std::string &proto, StringRef typestr, ClassKind ck) { std::string s; @@ -923,7 +923,7 @@ static std::string GenBuiltin(const std::string &name, const std::string &proto, bool splat = proto.find('a') != std::string::npos; - s += "__builtin_"; + s += "__builtin_neon_"; if (splat) { // Call the non-splat builtin: chop off the "_n" suffix from the name. std::string vname(name, 0, name.size()-2); @@ -1009,7 +1009,7 @@ static std::string GenBuiltin(const std::string &name, const std::string &proto, static std::string GenBuiltinDef(const std::string &name, const std::string &proto, StringRef typestr, ClassKind ck) { - std::string s("BUILTIN(__builtin_"); + std::string s("BUILTIN(__builtin_neon_"); // If all types are the same size, bitcasting the args will take care // of arg checking. The actual signedness etc. will be taken care of with @@ -1354,11 +1354,11 @@ void NeonEmitter::runHeader(raw_ostream &OS) { } } if (mask) - OS << "case ARM::BI__builtin_" + OS << "case ARM::BI__builtin_neon_" << MangleName(name, TypeVec[si], ClassB) << ": mask = " << "0x" << utohexstr(mask) << "; break;\n"; if (qmask) - OS << "case ARM::BI__builtin_" + OS << "case ARM::BI__builtin_neon_" << MangleName(name, TypeVec[qi], ClassB) << ": mask = " << "0x" << utohexstr(qmask) << "; break;\n"; } @@ -1446,7 +1446,7 @@ void NeonEmitter::runHeader(raw_ostream &OS) { case 'i': ie = ii + 1; break; } } - OS << "case ARM::BI__builtin_" << MangleName(name, TypeVec[ti], ck) + OS << "case ARM::BI__builtin_neon_" << MangleName(name, TypeVec[ti], ck) << ": i = " << immidx << "; " << rangestr << "; break;\n"; } } -- cgit v1.1 From e6b8bf8c4a74d48ad5c46c37f3754361acdeda61 Mon Sep 17 00:00:00 2001 From: Owen Anderson Date: Fri, 24 Jun 2011 23:02:22 +0000 Subject: The scheduler needs to be aware on the existence of untyped nodes when it performs type propagation for EXTRACT_SUBREG. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133838 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp index dbc623b..f03bf10 100644 --- a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp +++ b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp @@ -521,7 +521,8 @@ void ScheduleDAGSDNodes::RegDefIter::Advance() { if (!Node->hasAnyUseOfValue(DefIdx)) continue; if (Node->isMachineOpcode() && - Node->getMachineOpcode() == TargetOpcode::EXTRACT_SUBREG) { + Node->getMachineOpcode() == TargetOpcode::EXTRACT_SUBREG && + Node->getOperand(0).getValueType() != MVT::untyped) { // Propagate the incoming (full-register) type. I doubt it's needed. ValueType = Node->getOperand(0).getValueType(); } -- cgit v1.1 From ba8297ec08cdf7ae0c1e0c18ce07922e1f822643 Mon Sep 17 00:00:00 2001 From: Jim Grosbach Date: Fri, 24 Jun 2011 23:44:37 +0000 Subject: Refactor MachO relocation generaration into the Target directories. Move the target-specific RecordRelocation logic out of the generic MC MachObjectWriter and into the target-specific object writers. This allows nuking quite a bit of target knowledge from the supposedly target-independent bits in lib/MC. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133844 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/MC/MCMachObjectWriter.h | 192 ++++++ lib/MC/MachObjectWriter.cpp | 1004 +------------------------------- lib/Target/ARM/ARMMachObjectWriter.cpp | 357 ++++++++++++ lib/Target/PowerPC/PPCAsmBackend.cpp | 6 + lib/Target/X86/X86MachObjectWriter.cpp | 522 +++++++++++++++++ 5 files changed, 1096 insertions(+), 985 deletions(-) diff --git a/include/llvm/MC/MCMachObjectWriter.h b/include/llvm/MC/MCMachObjectWriter.h index ec51031..9bb598f 100644 --- a/include/llvm/MC/MCMachObjectWriter.h +++ b/include/llvm/MC/MCMachObjectWriter.h @@ -10,11 +10,20 @@ #ifndef LLVM_MC_MCMACHOBJECTWRITER_H #define LLVM_MC_MCMACHOBJECTWRITER_H +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/MC/MCExpr.h" #include "llvm/MC/MCObjectWriter.h" +#include "llvm/Object/MachOFormat.h" #include "llvm/Support/DataTypes.h" +#include namespace llvm { +class MCSectionData; +class MachObjectWriter; + class MCMachObjectTargetWriter { const unsigned Is64Bit : 1; const uint32_t CPUType; @@ -48,8 +57,191 @@ public: } /// @} + + /// @name API + /// @{ + + virtual void RecordRelocation(MachObjectWriter *Writer, + const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, + MCValue Target, + uint64_t &FixedValue) = 0; + + /// @} }; +class MachObjectWriter : public MCObjectWriter { + /// MachSymbolData - Helper struct for containing some precomputed information + /// on symbols. + struct MachSymbolData { + MCSymbolData *SymbolData; + uint64_t StringIndex; + uint8_t SectionIndex; + + // Support lexicographic sorting. + bool operator<(const MachSymbolData &RHS) const; + }; + + /// The target specific Mach-O writer instance. + llvm::OwningPtr TargetObjectWriter; + + /// @name Relocation Data + /// @{ + + llvm::DenseMap > Relocations; + llvm::DenseMap IndirectSymBase; + + /// @} + /// @name Symbol Table Data + /// @{ + + SmallString<256> StringTable; + std::vector LocalSymbolData; + std::vector ExternalSymbolData; + std::vector UndefinedSymbolData; + + /// @} + +public: + MachObjectWriter(MCMachObjectTargetWriter *MOTW, raw_ostream &_OS, + bool _IsLittleEndian) + : MCObjectWriter(_OS, _IsLittleEndian), TargetObjectWriter(MOTW) { + } + + /// @name Utility Methods + /// @{ + + bool isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind); + + SectionAddrMap SectionAddress; + + SectionAddrMap &getSectionAddressMap() { return SectionAddress; } + + uint64_t getSectionAddress(const MCSectionData* SD) const { + return SectionAddress.lookup(SD); + } + uint64_t getSymbolAddress(const MCSymbolData* SD, + const MCAsmLayout &Layout) const; + + uint64_t getFragmentAddress(const MCFragment *Fragment, + const MCAsmLayout &Layout) const; + + uint64_t getPaddingSize(const MCSectionData *SD, + const MCAsmLayout &Layout) const; + + bool doesSymbolRequireExternRelocation(const MCSymbolData *SD); + + /// @} + + /// @name Target Writer Proxy Accessors + /// @{ + + bool is64Bit() const { return TargetObjectWriter->is64Bit(); } + bool isARM() const { + uint32_t CPUType = TargetObjectWriter->getCPUType() & + ~object::mach::CTFM_ArchMask; + return CPUType == object::mach::CTM_ARM; + } + + /// @} + + void WriteHeader(unsigned NumLoadCommands, unsigned LoadCommandsSize, + bool SubsectionsViaSymbols); + + /// WriteSegmentLoadCommand - Write a segment load command. + /// + /// \arg NumSections - The number of sections in this segment. + /// \arg SectionDataSize - The total size of the sections. + void WriteSegmentLoadCommand(unsigned NumSections, + uint64_t VMSize, + uint64_t SectionDataStartOffset, + uint64_t SectionDataSize); + + void WriteSection(const MCAssembler &Asm, const MCAsmLayout &Layout, + const MCSectionData &SD, uint64_t FileOffset, + uint64_t RelocationsStart, unsigned NumRelocations); + + void WriteSymtabLoadCommand(uint32_t SymbolOffset, uint32_t NumSymbols, + uint32_t StringTableOffset, + uint32_t StringTableSize); + + void WriteDysymtabLoadCommand(uint32_t FirstLocalSymbol, + uint32_t NumLocalSymbols, + uint32_t FirstExternalSymbol, + uint32_t NumExternalSymbols, + uint32_t FirstUndefinedSymbol, + uint32_t NumUndefinedSymbols, + uint32_t IndirectSymbolOffset, + uint32_t NumIndirectSymbols); + + void WriteNlist(MachSymbolData &MSD, const MCAsmLayout &Layout); + + // FIXME: We really need to improve the relocation validation. Basically, we + // want to implement a separate computation which evaluates the relocation + // entry as the linker would, and verifies that the resultant fixup value is + // exactly what the encoder wanted. This will catch several classes of + // problems: + // + // - Relocation entry bugs, the two algorithms are unlikely to have the same + // exact bug. + // + // - Relaxation issues, where we forget to relax something. + // + // - Input errors, where something cannot be correctly encoded. 'as' allows + // these through in many cases. + + void addRelocation(const MCSectionData *SD, + object::macho::RelocationEntry &MRE) { + Relocations[SD].push_back(MRE); + } + + void RecordScatteredRelocation(const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, MCValue Target, + unsigned Log2Size, + uint64_t &FixedValue); + + void RecordTLVPRelocation(const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, MCValue Target, + uint64_t &FixedValue); + + void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, + const MCFragment *Fragment, const MCFixup &Fixup, + MCValue Target, uint64_t &FixedValue); + + void BindIndirectSymbols(MCAssembler &Asm); + + /// ComputeSymbolTable - Compute the symbol table data + /// + /// \param StringTable [out] - The string table data. + /// \param StringIndexMap [out] - Map from symbol names to offsets in the + /// string table. + void ComputeSymbolTable(MCAssembler &Asm, SmallString<256> &StringTable, + std::vector &LocalSymbolData, + std::vector &ExternalSymbolData, + std::vector &UndefinedSymbolData); + + void computeSectionAddresses(const MCAssembler &Asm, + const MCAsmLayout &Layout); + + void ExecutePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout); + + virtual bool IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, + const MCSymbolData &DataA, + const MCFragment &FB, + bool InSet, + bool IsPCRel) const; + + void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout); +}; + + /// \brief Construct a new Mach-O writer instance. /// /// This routine takes ownership of the target writer subclass. diff --git a/lib/MC/MachObjectWriter.cpp b/lib/MC/MachObjectWriter.cpp index e11b9df..69efe23 100644 --- a/lib/MC/MachObjectWriter.cpp +++ b/lib/MC/MachObjectWriter.cpp @@ -23,34 +23,12 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Target/TargetAsmBackend.h" -// FIXME: Gross. -#include "../Target/ARM/ARMFixupKinds.h" -#include "../Target/X86/X86FixupKinds.h" - #include using namespace llvm; using namespace llvm::object; -// FIXME: this has been copied from (or to) X86AsmBackend.cpp -static unsigned getFixupKindLog2Size(unsigned Kind) { - switch (Kind) { - default: - llvm_unreachable("invalid fixup kind!"); - case FK_PCRel_1: - case FK_Data_1: return 0; - case FK_PCRel_2: - case FK_Data_2: return 1; - case FK_PCRel_4: - // FIXME: Remove these!!! - case X86::reloc_riprel_4byte: - case X86::reloc_riprel_4byte_movq_load: - case X86::reloc_signed_4byte: - case FK_Data_4: return 2; - case FK_Data_8: return 3; - } -} - -static bool doesSymbolRequireExternRelocation(MCSymbolData *SD) { +bool MachObjectWriter:: +doesSymbolRequireExternRelocation(const MCSymbolData *SD) { // Undefined symbols are always extern. if (SD->Symbol->isUndefined()) return true; @@ -64,207 +42,24 @@ static bool doesSymbolRequireExternRelocation(MCSymbolData *SD) { return false; } -namespace { - -class MachObjectWriter : public MCObjectWriter { - /// MachSymbolData - Helper struct for containing some precomputed information - /// on symbols. - struct MachSymbolData { - MCSymbolData *SymbolData; - uint64_t StringIndex; - uint8_t SectionIndex; - - // Support lexicographic sorting. - bool operator<(const MachSymbolData &RHS) const { - return SymbolData->getSymbol().getName() < - RHS.SymbolData->getSymbol().getName(); - } - }; - - /// The target specific Mach-O writer instance. - llvm::OwningPtr TargetObjectWriter; - - /// @name Relocation Data - /// @{ - - llvm::DenseMap > Relocations; - llvm::DenseMap IndirectSymBase; - - /// @} - /// @name Symbol Table Data - /// @{ - - SmallString<256> StringTable; - std::vector LocalSymbolData; - std::vector ExternalSymbolData; - std::vector UndefinedSymbolData; - - /// @} - -private: - /// @name Utility Methods - /// @{ - - bool isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind) { - const MCFixupKindInfo &FKI = Asm.getBackend().getFixupKindInfo( - (MCFixupKind) Kind); - - return FKI.Flags & MCFixupKindInfo::FKF_IsPCRel; - } - - /// @} - - SectionAddrMap SectionAddress; - uint64_t getSectionAddress(const MCSectionData* SD) const { - return SectionAddress.lookup(SD); - } - uint64_t getSymbolAddress(const MCSymbolData* SD, - const MCAsmLayout &Layout) const; - - uint64_t getFragmentAddress(const MCFragment *Fragment, - const MCAsmLayout &Layout) const { - return getSectionAddress(Fragment->getParent()) + - Layout.getFragmentOffset(Fragment); - } - - uint64_t getPaddingSize(const MCSectionData *SD, - const MCAsmLayout &Layout) const; -public: - MachObjectWriter(MCMachObjectTargetWriter *MOTW, raw_ostream &_OS, - bool _IsLittleEndian) - : MCObjectWriter(_OS, _IsLittleEndian), TargetObjectWriter(MOTW) { - } - - /// @name Target Writer Proxy Accessors - /// @{ +bool MachObjectWriter:: +MachSymbolData::operator<(const MachSymbolData &RHS) const { + return SymbolData->getSymbol().getName() < + RHS.SymbolData->getSymbol().getName(); +} - bool is64Bit() const { return TargetObjectWriter->is64Bit(); } - bool isARM() const { - uint32_t CPUType = TargetObjectWriter->getCPUType() & ~mach::CTFM_ArchMask; - return CPUType == mach::CTM_ARM; - } +bool MachObjectWriter::isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind) { + const MCFixupKindInfo &FKI = Asm.getBackend().getFixupKindInfo( + (MCFixupKind) Kind); - /// @} - - void WriteHeader(unsigned NumLoadCommands, unsigned LoadCommandsSize, - bool SubsectionsViaSymbols); - - /// WriteSegmentLoadCommand - Write a segment load command. - /// - /// \arg NumSections - The number of sections in this segment. - /// \arg SectionDataSize - The total size of the sections. - void WriteSegmentLoadCommand(unsigned NumSections, - uint64_t VMSize, - uint64_t SectionDataStartOffset, - uint64_t SectionDataSize); - - void WriteSection(const MCAssembler &Asm, const MCAsmLayout &Layout, - const MCSectionData &SD, uint64_t FileOffset, - uint64_t RelocationsStart, unsigned NumRelocations); - - void WriteSymtabLoadCommand(uint32_t SymbolOffset, uint32_t NumSymbols, - uint32_t StringTableOffset, - uint32_t StringTableSize); - - void WriteDysymtabLoadCommand(uint32_t FirstLocalSymbol, - uint32_t NumLocalSymbols, - uint32_t FirstExternalSymbol, - uint32_t NumExternalSymbols, - uint32_t FirstUndefinedSymbol, - uint32_t NumUndefinedSymbols, - uint32_t IndirectSymbolOffset, - uint32_t NumIndirectSymbols); - - void WriteNlist(MachSymbolData &MSD, const MCAsmLayout &Layout); - - // FIXME: We really need to improve the relocation validation. Basically, we - // want to implement a separate computation which evaluates the relocation - // entry as the linker would, and verifies that the resultant fixup value is - // exactly what the encoder wanted. This will catch several classes of - // problems: - // - // - Relocation entry bugs, the two algorithms are unlikely to have the same - // exact bug. - // - // - Relaxation issues, where we forget to relax something. - // - // - Input errors, where something cannot be correctly encoded. 'as' allows - // these through in many cases. + return FKI.Flags & MCFixupKindInfo::FKF_IsPCRel; +} - static bool isFixupKindRIPRel(unsigned Kind) { - return Kind == X86::reloc_riprel_4byte || - Kind == X86::reloc_riprel_4byte_movq_load; - } - void RecordX86_64Relocation(const MCAssembler &Asm, const MCAsmLayout &Layout, - const MCFragment *Fragment, - const MCFixup &Fixup, MCValue Target, - uint64_t &FixedValue); - - void RecordScatteredRelocation(const MCAssembler &Asm, - const MCAsmLayout &Layout, - const MCFragment *Fragment, - const MCFixup &Fixup, MCValue Target, - unsigned Log2Size, - uint64_t &FixedValue); - - void RecordARMScatteredRelocation(const MCAssembler &Asm, - const MCAsmLayout &Layout, - const MCFragment *Fragment, - const MCFixup &Fixup, MCValue Target, - unsigned Log2Size, - uint64_t &FixedValue); - - void RecordARMMovwMovtRelocation(const MCAssembler &Asm, - const MCAsmLayout &Layout, - const MCFragment *Fragment, - const MCFixup &Fixup, MCValue Target, - uint64_t &FixedValue); - - void RecordTLVPRelocation(const MCAssembler &Asm, - const MCAsmLayout &Layout, - const MCFragment *Fragment, - const MCFixup &Fixup, MCValue Target, - uint64_t &FixedValue); - - static bool getARMFixupKindMachOInfo(unsigned Kind, unsigned &RelocType, - unsigned &Log2Size); - - void RecordARMRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, - const MCFragment *Fragment, const MCFixup &Fixup, - MCValue Target, uint64_t &FixedValue); - - void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, - const MCFragment *Fragment, const MCFixup &Fixup, - MCValue Target, uint64_t &FixedValue); - - void BindIndirectSymbols(MCAssembler &Asm); - - /// ComputeSymbolTable - Compute the symbol table data - /// - /// \param StringTable [out] - The string table data. - /// \param StringIndexMap [out] - Map from symbol names to offsets in the - /// string table. - void ComputeSymbolTable(MCAssembler &Asm, SmallString<256> &StringTable, - std::vector &LocalSymbolData, - std::vector &ExternalSymbolData, - std::vector &UndefinedSymbolData); - - void computeSectionAddresses(const MCAssembler &Asm, - const MCAsmLayout &Layout); - - void ExecutePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout); - - virtual bool IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, - const MCSymbolData &DataA, - const MCFragment &FB, - bool InSet, - bool IsPCRel) const; - - void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout); -}; - -} // end anonymous namespace +uint64_t MachObjectWriter::getFragmentAddress(const MCFragment *Fragment, + const MCAsmLayout &Layout) const { + return getSectionAddress(Fragment->getParent()) + + Layout.getFragmentOffset(Fragment); +} uint64_t MachObjectWriter::getSymbolAddress(const MCSymbolData* SD, const MCAsmLayout &Layout) const { @@ -556,775 +351,14 @@ void MachObjectWriter::WriteNlist(MachSymbolData &MSD, Write32(Address); } -void MachObjectWriter::RecordX86_64Relocation(const MCAssembler &Asm, - const MCAsmLayout &Layout, - const MCFragment *Fragment, - const MCFixup &Fixup, - MCValue Target, - uint64_t &FixedValue) { - unsigned IsPCRel = isFixupKindPCRel(Asm, Fixup.getKind()); - unsigned IsRIPRel = isFixupKindRIPRel(Fixup.getKind()); - unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind()); - - // See . - uint32_t FixupOffset = - Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); - uint32_t FixupAddress = - getFragmentAddress(Fragment, Layout) + Fixup.getOffset(); - int64_t Value = 0; - unsigned Index = 0; - unsigned IsExtern = 0; - unsigned Type = 0; - - Value = Target.getConstant(); - - if (IsPCRel) { - // Compensate for the relocation offset, Darwin x86_64 relocations only have - // the addend and appear to have attempted to define it to be the actual - // expression addend without the PCrel bias. However, instructions with data - // following the relocation are not accommodated for (see comment below - // regarding SIGNED{1,2,4}), so it isn't exactly that either. - Value += 1LL << Log2Size; - } - - if (Target.isAbsolute()) { // constant - // SymbolNum of 0 indicates the absolute section. - Type = macho::RIT_X86_64_Unsigned; - Index = 0; - - // FIXME: I believe this is broken, I don't think the linker can understand - // it. I think it would require a local relocation, but I'm not sure if that - // would work either. The official way to get an absolute PCrel relocation - // is to use an absolute symbol (which we don't support yet). - if (IsPCRel) { - IsExtern = 1; - Type = macho::RIT_X86_64_Branch; - } - } else if (Target.getSymB()) { // A - B + constant - const MCSymbol *A = &Target.getSymA()->getSymbol(); - MCSymbolData &A_SD = Asm.getSymbolData(*A); - const MCSymbolData *A_Base = Asm.getAtom(&A_SD); - - const MCSymbol *B = &Target.getSymB()->getSymbol(); - MCSymbolData &B_SD = Asm.getSymbolData(*B); - const MCSymbolData *B_Base = Asm.getAtom(&B_SD); - - // Neither symbol can be modified. - if (Target.getSymA()->getKind() != MCSymbolRefExpr::VK_None || - Target.getSymB()->getKind() != MCSymbolRefExpr::VK_None) - report_fatal_error("unsupported relocation of modified symbol"); - - // We don't support PCrel relocations of differences. Darwin 'as' doesn't - // implement most of these correctly. - if (IsPCRel) - report_fatal_error("unsupported pc-relative relocation of difference"); - - // The support for the situation where one or both of the symbols would - // require a local relocation is handled just like if the symbols were - // external. This is certainly used in the case of debug sections where the - // section has only temporary symbols and thus the symbols don't have base - // symbols. This is encoded using the section ordinal and non-extern - // relocation entries. - - // Darwin 'as' doesn't emit correct relocations for this (it ends up with a - // single SIGNED relocation); reject it for now. Except the case where both - // symbols don't have a base, equal but both NULL. - if (A_Base == B_Base && A_Base) - report_fatal_error("unsupported relocation with identical base"); - - Value += getSymbolAddress(&A_SD, Layout) - - (A_Base == NULL ? 0 : getSymbolAddress(A_Base, Layout)); - Value -= getSymbolAddress(&B_SD, Layout) - - (B_Base == NULL ? 0 : getSymbolAddress(B_Base, Layout)); - - if (A_Base) { - Index = A_Base->getIndex(); - IsExtern = 1; - } - else { - Index = A_SD.getFragment()->getParent()->getOrdinal() + 1; - IsExtern = 0; - } - Type = macho::RIT_X86_64_Unsigned; - - macho::RelocationEntry MRE; - MRE.Word0 = FixupOffset; - MRE.Word1 = ((Index << 0) | - (IsPCRel << 24) | - (Log2Size << 25) | - (IsExtern << 27) | - (Type << 28)); - Relocations[Fragment->getParent()].push_back(MRE); - - if (B_Base) { - Index = B_Base->getIndex(); - IsExtern = 1; - } - else { - Index = B_SD.getFragment()->getParent()->getOrdinal() + 1; - IsExtern = 0; - } - Type = macho::RIT_X86_64_Subtractor; - } else { - const MCSymbol *Symbol = &Target.getSymA()->getSymbol(); - MCSymbolData &SD = Asm.getSymbolData(*Symbol); - const MCSymbolData *Base = Asm.getAtom(&SD); - - // Relocations inside debug sections always use local relocations when - // possible. This seems to be done because the debugger doesn't fully - // understand x86_64 relocation entries, and expects to find values that - // have already been fixed up. - if (Symbol->isInSection()) { - const MCSectionMachO &Section = static_cast( - Fragment->getParent()->getSection()); - if (Section.hasAttribute(MCSectionMachO::S_ATTR_DEBUG)) - Base = 0; - } - - // x86_64 almost always uses external relocations, except when there is no - // symbol to use as a base address (a local symbol with no preceding - // non-local symbol). - if (Base) { - Index = Base->getIndex(); - IsExtern = 1; - - // Add the local offset, if needed. - if (Base != &SD) - Value += Layout.getSymbolOffset(&SD) - Layout.getSymbolOffset(Base); - } else if (Symbol->isInSection() && !Symbol->isVariable()) { - // The index is the section ordinal (1-based). - Index = SD.getFragment()->getParent()->getOrdinal() + 1; - IsExtern = 0; - Value += getSymbolAddress(&SD, Layout); - - if (IsPCRel) - Value -= FixupAddress + (1 << Log2Size); - } else if (Symbol->isVariable()) { - const MCExpr *Value = Symbol->getVariableValue(); - int64_t Res; - bool isAbs = Value->EvaluateAsAbsolute(Res, Layout, SectionAddress); - if (isAbs) { - FixedValue = Res; - return; - } else { - report_fatal_error("unsupported relocation of variable '" + - Symbol->getName() + "'"); - } - } else { - report_fatal_error("unsupported relocation of undefined symbol '" + - Symbol->getName() + "'"); - } - - MCSymbolRefExpr::VariantKind Modifier = Target.getSymA()->getKind(); - if (IsPCRel) { - if (IsRIPRel) { - if (Modifier == MCSymbolRefExpr::VK_GOTPCREL) { - // x86_64 distinguishes movq foo@GOTPCREL so that the linker can - // rewrite the movq to an leaq at link time if the symbol ends up in - // the same linkage unit. - if (unsigned(Fixup.getKind()) == X86::reloc_riprel_4byte_movq_load) - Type = macho::RIT_X86_64_GOTLoad; - else - Type = macho::RIT_X86_64_GOT; - } else if (Modifier == MCSymbolRefExpr::VK_TLVP) { - Type = macho::RIT_X86_64_TLV; - } else if (Modifier != MCSymbolRefExpr::VK_None) { - report_fatal_error("unsupported symbol modifier in relocation"); - } else { - Type = macho::RIT_X86_64_Signed; - - // The Darwin x86_64 relocation format has a problem where it cannot - // encode an address (L + ) which is outside the atom - // containing L. Generally, this shouldn't occur but it does - // happen when we have a RIPrel instruction with data following the - // relocation entry (e.g., movb $012, L0(%rip)). Even with the PCrel - // adjustment Darwin x86_64 uses, the offset is still negative and the - // linker has no way to recognize this. - // - // To work around this, Darwin uses several special relocation types - // to indicate the offsets. However, the specification or - // implementation of these seems to also be incomplete; they should - // adjust the addend as well based on the actual encoded instruction - // (the additional bias), but instead appear to just look at the final - // offset. - switch (-(Target.getConstant() + (1LL << Log2Size))) { - case 1: Type = macho::RIT_X86_64_Signed1; break; - case 2: Type = macho::RIT_X86_64_Signed2; break; - case 4: Type = macho::RIT_X86_64_Signed4; break; - } - } - } else { - if (Modifier != MCSymbolRefExpr::VK_None) - report_fatal_error("unsupported symbol modifier in branch " - "relocation"); - - Type = macho::RIT_X86_64_Branch; - } - } else { - if (Modifier == MCSymbolRefExpr::VK_GOT) { - Type = macho::RIT_X86_64_GOT; - } else if (Modifier == MCSymbolRefExpr::VK_GOTPCREL) { - // GOTPCREL is allowed as a modifier on non-PCrel instructions, in which - // case all we do is set the PCrel bit in the relocation entry; this is - // used with exception handling, for example. The source is required to - // include any necessary offset directly. - Type = macho::RIT_X86_64_GOT; - IsPCRel = 1; - } else if (Modifier == MCSymbolRefExpr::VK_TLVP) { - report_fatal_error("TLVP symbol modifier should have been rip-rel"); - } else if (Modifier != MCSymbolRefExpr::VK_None) - report_fatal_error("unsupported symbol modifier in relocation"); - else - Type = macho::RIT_X86_64_Unsigned; - } - } - - // x86_64 always writes custom values into the fixups. - FixedValue = Value; - - // struct relocation_info (8 bytes) - macho::RelocationEntry MRE; - MRE.Word0 = FixupOffset; - MRE.Word1 = ((Index << 0) | - (IsPCRel << 24) | - (Log2Size << 25) | - (IsExtern << 27) | - (Type << 28)); - Relocations[Fragment->getParent()].push_back(MRE); -} - -void MachObjectWriter::RecordScatteredRelocation(const MCAssembler &Asm, - const MCAsmLayout &Layout, - const MCFragment *Fragment, - const MCFixup &Fixup, - MCValue Target, - unsigned Log2Size, - uint64_t &FixedValue) { - uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); - unsigned IsPCRel = isFixupKindPCRel(Asm, Fixup.getKind()); - unsigned Type = macho::RIT_Vanilla; - - // See . - const MCSymbol *A = &Target.getSymA()->getSymbol(); - MCSymbolData *A_SD = &Asm.getSymbolData(*A); - - if (!A_SD->getFragment()) - report_fatal_error("symbol '" + A->getName() + - "' can not be undefined in a subtraction expression"); - - uint32_t Value = getSymbolAddress(A_SD, Layout); - uint64_t SecAddr = getSectionAddress(A_SD->getFragment()->getParent()); - FixedValue += SecAddr; - uint32_t Value2 = 0; - - if (const MCSymbolRefExpr *B = Target.getSymB()) { - MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol()); - - if (!B_SD->getFragment()) - report_fatal_error("symbol '" + B->getSymbol().getName() + - "' can not be undefined in a subtraction expression"); - - // Select the appropriate difference relocation type. - // - // Note that there is no longer any semantic difference between these two - // relocation types from the linkers point of view, this is done solely for - // pedantic compatibility with 'as'. - Type = A_SD->isExternal() ? (unsigned)macho::RIT_Difference : - (unsigned)macho::RIT_Generic_LocalDifference; - Value2 = getSymbolAddress(B_SD, Layout); - FixedValue -= getSectionAddress(B_SD->getFragment()->getParent()); - } - - // Relocations are written out in reverse order, so the PAIR comes first. - if (Type == macho::RIT_Difference || - Type == macho::RIT_Generic_LocalDifference) { - macho::RelocationEntry MRE; - MRE.Word0 = ((0 << 0) | - (macho::RIT_Pair << 24) | - (Log2Size << 28) | - (IsPCRel << 30) | - macho::RF_Scattered); - MRE.Word1 = Value2; - Relocations[Fragment->getParent()].push_back(MRE); - } - - macho::RelocationEntry MRE; - MRE.Word0 = ((FixupOffset << 0) | - (Type << 24) | - (Log2Size << 28) | - (IsPCRel << 30) | - macho::RF_Scattered); - MRE.Word1 = Value; - Relocations[Fragment->getParent()].push_back(MRE); -} - -void MachObjectWriter::RecordARMScatteredRelocation(const MCAssembler &Asm, - const MCAsmLayout &Layout, - const MCFragment *Fragment, - const MCFixup &Fixup, - MCValue Target, - unsigned Log2Size, - uint64_t &FixedValue) { - uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); - unsigned IsPCRel = isFixupKindPCRel(Asm, Fixup.getKind()); - unsigned Type = macho::RIT_Vanilla; - - // See . - const MCSymbol *A = &Target.getSymA()->getSymbol(); - MCSymbolData *A_SD = &Asm.getSymbolData(*A); - - if (!A_SD->getFragment()) - report_fatal_error("symbol '" + A->getName() + - "' can not be undefined in a subtraction expression"); - - uint32_t Value = getSymbolAddress(A_SD, Layout); - uint64_t SecAddr = getSectionAddress(A_SD->getFragment()->getParent()); - FixedValue += SecAddr; - uint32_t Value2 = 0; - - if (const MCSymbolRefExpr *B = Target.getSymB()) { - MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol()); - - if (!B_SD->getFragment()) - report_fatal_error("symbol '" + B->getSymbol().getName() + - "' can not be undefined in a subtraction expression"); - - // Select the appropriate difference relocation type. - Type = macho::RIT_Difference; - Value2 = getSymbolAddress(B_SD, Layout); - FixedValue -= getSectionAddress(B_SD->getFragment()->getParent()); - } - - // Relocations are written out in reverse order, so the PAIR comes first. - if (Type == macho::RIT_Difference || - Type == macho::RIT_Generic_LocalDifference) { - macho::RelocationEntry MRE; - MRE.Word0 = ((0 << 0) | - (macho::RIT_Pair << 24) | - (Log2Size << 28) | - (IsPCRel << 30) | - macho::RF_Scattered); - MRE.Word1 = Value2; - Relocations[Fragment->getParent()].push_back(MRE); - } - - macho::RelocationEntry MRE; - MRE.Word0 = ((FixupOffset << 0) | - (Type << 24) | - (Log2Size << 28) | - (IsPCRel << 30) | - macho::RF_Scattered); - MRE.Word1 = Value; - Relocations[Fragment->getParent()].push_back(MRE); -} - -void MachObjectWriter::RecordARMMovwMovtRelocation(const MCAssembler &Asm, - const MCAsmLayout &Layout, - const MCFragment *Fragment, - const MCFixup &Fixup, - MCValue Target, - uint64_t &FixedValue) { - uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); - unsigned IsPCRel = isFixupKindPCRel(Asm, Fixup.getKind()); - unsigned Type = macho::RIT_ARM_Half; - - // See . - const MCSymbol *A = &Target.getSymA()->getSymbol(); - MCSymbolData *A_SD = &Asm.getSymbolData(*A); - - if (!A_SD->getFragment()) - report_fatal_error("symbol '" + A->getName() + - "' can not be undefined in a subtraction expression"); - - uint32_t Value = getSymbolAddress(A_SD, Layout); - uint32_t Value2 = 0; - uint64_t SecAddr = getSectionAddress(A_SD->getFragment()->getParent()); - FixedValue += SecAddr; - - if (const MCSymbolRefExpr *B = Target.getSymB()) { - MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol()); - - if (!B_SD->getFragment()) - report_fatal_error("symbol '" + B->getSymbol().getName() + - "' can not be undefined in a subtraction expression"); - - // Select the appropriate difference relocation type. - Type = macho::RIT_ARM_HalfDifference; - Value2 = getSymbolAddress(B_SD, Layout); - FixedValue -= getSectionAddress(B_SD->getFragment()->getParent()); - } - - // Relocations are written out in reverse order, so the PAIR comes first. - // ARM_RELOC_HALF and ARM_RELOC_HALF_SECTDIFF abuse the r_length field: - // - // For these two r_type relocations they always have a pair following them and - // the r_length bits are used differently. The encoding of the r_length is as - // follows: - // low bit of r_length: - // 0 - :lower16: for movw instructions - // 1 - :upper16: for movt instructions - // high bit of r_length: - // 0 - arm instructions - // 1 - thumb instructions - // the other half of the relocated expression is in the following pair - // relocation entry in the the low 16 bits of r_address field. - unsigned ThumbBit = 0; - unsigned MovtBit = 0; - switch ((unsigned)Fixup.getKind()) { - default: break; - case ARM::fixup_arm_movt_hi16: - case ARM::fixup_arm_movt_hi16_pcrel: - MovtBit = 1; - break; - case ARM::fixup_t2_movt_hi16: - case ARM::fixup_t2_movt_hi16_pcrel: - MovtBit = 1; - // Fallthrough - case ARM::fixup_t2_movw_lo16: - case ARM::fixup_t2_movw_lo16_pcrel: - ThumbBit = 1; - break; - } - - - if (Type == macho::RIT_ARM_HalfDifference) { - uint32_t OtherHalf = MovtBit - ? (FixedValue & 0xffff) : ((FixedValue & 0xffff0000) >> 16); - - macho::RelocationEntry MRE; - MRE.Word0 = ((OtherHalf << 0) | - (macho::RIT_Pair << 24) | - (MovtBit << 28) | - (ThumbBit << 29) | - (IsPCRel << 30) | - macho::RF_Scattered); - MRE.Word1 = Value2; - Relocations[Fragment->getParent()].push_back(MRE); - } - - macho::RelocationEntry MRE; - MRE.Word0 = ((FixupOffset << 0) | - (Type << 24) | - (MovtBit << 28) | - (ThumbBit << 29) | - (IsPCRel << 30) | - macho::RF_Scattered); - MRE.Word1 = Value; - Relocations[Fragment->getParent()].push_back(MRE); -} - -void MachObjectWriter::RecordTLVPRelocation(const MCAssembler &Asm, - const MCAsmLayout &Layout, - const MCFragment *Fragment, - const MCFixup &Fixup, - MCValue Target, - uint64_t &FixedValue) { - assert(Target.getSymA()->getKind() == MCSymbolRefExpr::VK_TLVP && - !is64Bit() && - "Should only be called with a 32-bit TLVP relocation!"); - - unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind()); - uint32_t Value = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); - unsigned IsPCRel = 0; - - // Get the symbol data. - MCSymbolData *SD_A = &Asm.getSymbolData(Target.getSymA()->getSymbol()); - unsigned Index = SD_A->getIndex(); - - // We're only going to have a second symbol in pic mode and it'll be a - // subtraction from the picbase. For 32-bit pic the addend is the difference - // between the picbase and the next address. For 32-bit static the addend is - // zero. - if (Target.getSymB()) { - // If this is a subtraction then we're pcrel. - uint32_t FixupAddress = - getFragmentAddress(Fragment, Layout) + Fixup.getOffset(); - MCSymbolData *SD_B = &Asm.getSymbolData(Target.getSymB()->getSymbol()); - IsPCRel = 1; - FixedValue = (FixupAddress - getSymbolAddress(SD_B, Layout) + - Target.getConstant()); - FixedValue += 1ULL << Log2Size; - } else { - FixedValue = 0; - } - - // struct relocation_info (8 bytes) - macho::RelocationEntry MRE; - MRE.Word0 = Value; - MRE.Word1 = ((Index << 0) | - (IsPCRel << 24) | - (Log2Size << 25) | - (1 << 27) | // Extern - (macho::RIT_Generic_TLV << 28)); // Type - Relocations[Fragment->getParent()].push_back(MRE); -} - -bool MachObjectWriter::getARMFixupKindMachOInfo(unsigned Kind, - unsigned &RelocType, - unsigned &Log2Size) { - RelocType = unsigned(macho::RIT_Vanilla); - Log2Size = ~0U; - - switch (Kind) { - default: - return false; - - case FK_Data_1: - Log2Size = llvm::Log2_32(1); - return true; - case FK_Data_2: - Log2Size = llvm::Log2_32(2); - return true; - case FK_Data_4: - Log2Size = llvm::Log2_32(4); - return true; - case FK_Data_8: - Log2Size = llvm::Log2_32(8); - return true; - - // Handle 24-bit branch kinds. - case ARM::fixup_arm_ldst_pcrel_12: - case ARM::fixup_arm_pcrel_10: - case ARM::fixup_arm_adr_pcrel_12: - case ARM::fixup_arm_condbranch: - case ARM::fixup_arm_uncondbranch: - RelocType = unsigned(macho::RIT_ARM_Branch24Bit); - // Report as 'long', even though that is not quite accurate. - Log2Size = llvm::Log2_32(4); - return true; - - // Handle Thumb branches. - case ARM::fixup_arm_thumb_br: - RelocType = unsigned(macho::RIT_ARM_ThumbBranch22Bit); - Log2Size = llvm::Log2_32(2); - return true; - - case ARM::fixup_t2_uncondbranch: - case ARM::fixup_arm_thumb_bl: - case ARM::fixup_arm_thumb_blx: - RelocType = unsigned(macho::RIT_ARM_ThumbBranch22Bit); - Log2Size = llvm::Log2_32(4); - return true; - - case ARM::fixup_arm_movt_hi16: - case ARM::fixup_arm_movt_hi16_pcrel: - case ARM::fixup_t2_movt_hi16: - case ARM::fixup_t2_movt_hi16_pcrel: - RelocType = unsigned(macho::RIT_ARM_HalfDifference); - // Report as 'long', even though that is not quite accurate. - Log2Size = llvm::Log2_32(4); - return true; - - case ARM::fixup_arm_movw_lo16: - case ARM::fixup_arm_movw_lo16_pcrel: - case ARM::fixup_t2_movw_lo16: - case ARM::fixup_t2_movw_lo16_pcrel: - RelocType = unsigned(macho::RIT_ARM_Half); - // Report as 'long', even though that is not quite accurate. - Log2Size = llvm::Log2_32(4); - return true; - } -} -void MachObjectWriter::RecordARMRelocation(const MCAssembler &Asm, - const MCAsmLayout &Layout, - const MCFragment *Fragment, - const MCFixup &Fixup, - MCValue Target, - uint64_t &FixedValue) { - unsigned IsPCRel = isFixupKindPCRel(Asm, Fixup.getKind()); - unsigned Log2Size; - unsigned RelocType = macho::RIT_Vanilla; - if (!getARMFixupKindMachOInfo(Fixup.getKind(), RelocType, Log2Size)) { - report_fatal_error("unknown ARM fixup kind!"); - return; - } - - // If this is a difference or a defined symbol plus an offset, then we need a - // scattered relocation entry. Differences always require scattered - // relocations. - if (Target.getSymB()) { - if (RelocType == macho::RIT_ARM_Half || - RelocType == macho::RIT_ARM_HalfDifference) - return RecordARMMovwMovtRelocation(Asm, Layout, Fragment, Fixup, - Target, FixedValue); - return RecordARMScatteredRelocation(Asm, Layout, Fragment, Fixup, - Target, Log2Size, FixedValue); - } - - // Get the symbol data, if any. - MCSymbolData *SD = 0; - if (Target.getSymA()) - SD = &Asm.getSymbolData(Target.getSymA()->getSymbol()); - - // FIXME: For other platforms, we need to use scattered relocations for - // internal relocations with offsets. If this is an internal relocation with - // an offset, it also needs a scattered relocation entry. - // - // Is this right for ARM? - uint32_t Offset = Target.getConstant(); - if (IsPCRel && RelocType == macho::RIT_Vanilla) - Offset += 1 << Log2Size; - if (Offset && SD && !doesSymbolRequireExternRelocation(SD)) - return RecordARMScatteredRelocation(Asm, Layout, Fragment, Fixup, Target, - Log2Size, FixedValue); - - // See . - uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); - unsigned Index = 0; - unsigned IsExtern = 0; - unsigned Type = 0; - - if (Target.isAbsolute()) { // constant - // FIXME! - report_fatal_error("FIXME: relocations to absolute targets " - "not yet implemented"); - } else { - // Resolve constant variables. - if (SD->getSymbol().isVariable()) { - int64_t Res; - if (SD->getSymbol().getVariableValue()->EvaluateAsAbsolute( - Res, Layout, SectionAddress)) { - FixedValue = Res; - return; - } - } - - // Check whether we need an external or internal relocation. - if (doesSymbolRequireExternRelocation(SD)) { - IsExtern = 1; - Index = SD->getIndex(); - - // For external relocations, make sure to offset the fixup value to - // compensate for the addend of the symbol address, if it was - // undefined. This occurs with weak definitions, for example. - if (!SD->Symbol->isUndefined()) - FixedValue -= Layout.getSymbolOffset(SD); - } else { - // The index is the section ordinal (1-based). - const MCSectionData &SymSD = Asm.getSectionData( - SD->getSymbol().getSection()); - Index = SymSD.getOrdinal() + 1; - FixedValue += getSectionAddress(&SymSD); - } - if (IsPCRel) - FixedValue -= getSectionAddress(Fragment->getParent()); - - // The type is determined by the fixup kind. - Type = RelocType; - } - - // struct relocation_info (8 bytes) - macho::RelocationEntry MRE; - MRE.Word0 = FixupOffset; - MRE.Word1 = ((Index << 0) | - (IsPCRel << 24) | - (Log2Size << 25) | - (IsExtern << 27) | - (Type << 28)); - Relocations[Fragment->getParent()].push_back(MRE); -} - void MachObjectWriter::RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, uint64_t &FixedValue) { - // FIXME: These needs to be factored into the target Mach-O writer. - if (isARM()) { - RecordARMRelocation(Asm, Layout, Fragment, Fixup, Target, FixedValue); - return; - } - if (is64Bit()) { - RecordX86_64Relocation(Asm, Layout, Fragment, Fixup, Target, FixedValue); - return; - } - - unsigned IsPCRel = isFixupKindPCRel(Asm, Fixup.getKind()); - unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind()); - - // If this is a 32-bit TLVP reloc it's handled a bit differently. - if (Target.getSymA() && - Target.getSymA()->getKind() == MCSymbolRefExpr::VK_TLVP) { - RecordTLVPRelocation(Asm, Layout, Fragment, Fixup, Target, FixedValue); - return; - } - - // If this is a difference or a defined symbol plus an offset, then we need a - // scattered relocation entry. Differences always require scattered - // relocations. - if (Target.getSymB()) - return RecordScatteredRelocation(Asm, Layout, Fragment, Fixup, - Target, Log2Size, FixedValue); - - // Get the symbol data, if any. - MCSymbolData *SD = 0; - if (Target.getSymA()) - SD = &Asm.getSymbolData(Target.getSymA()->getSymbol()); - - // If this is an internal relocation with an offset, it also needs a scattered - // relocation entry. - uint32_t Offset = Target.getConstant(); - if (IsPCRel) - Offset += 1 << Log2Size; - if (Offset && SD && !doesSymbolRequireExternRelocation(SD)) - return RecordScatteredRelocation(Asm, Layout, Fragment, Fixup, - Target, Log2Size, FixedValue); - - // See . - uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); - unsigned Index = 0; - unsigned IsExtern = 0; - unsigned Type = 0; - - if (Target.isAbsolute()) { // constant - // SymbolNum of 0 indicates the absolute section. - // - // FIXME: Currently, these are never generated (see code below). I cannot - // find a case where they are actually emitted. - Type = macho::RIT_Vanilla; - } else { - // Resolve constant variables. - if (SD->getSymbol().isVariable()) { - int64_t Res; - if (SD->getSymbol().getVariableValue()->EvaluateAsAbsolute( - Res, Layout, SectionAddress)) { - FixedValue = Res; - return; - } - } - - // Check whether we need an external or internal relocation. - if (doesSymbolRequireExternRelocation(SD)) { - IsExtern = 1; - Index = SD->getIndex(); - // For external relocations, make sure to offset the fixup value to - // compensate for the addend of the symbol address, if it was - // undefined. This occurs with weak definitions, for example. - if (!SD->Symbol->isUndefined()) - FixedValue -= Layout.getSymbolOffset(SD); - } else { - // The index is the section ordinal (1-based). - const MCSectionData &SymSD = Asm.getSectionData( - SD->getSymbol().getSection()); - Index = SymSD.getOrdinal() + 1; - FixedValue += getSectionAddress(&SymSD); - } - if (IsPCRel) - FixedValue -= getSectionAddress(Fragment->getParent()); - - Type = macho::RIT_Vanilla; - } - - // struct relocation_info (8 bytes) - macho::RelocationEntry MRE; - MRE.Word0 = FixupOffset; - MRE.Word1 = ((Index << 0) | - (IsPCRel << 24) | - (Log2Size << 25) | - (IsExtern << 27) | - (Type << 28)); - Relocations[Fragment->getParent()].push_back(MRE); + TargetObjectWriter->RecordRelocation(this, Asm, Layout, Fragment, Fixup, + Target, FixedValue); } void MachObjectWriter::BindIndirectSymbols(MCAssembler &Asm) { diff --git a/lib/Target/ARM/ARMMachObjectWriter.cpp b/lib/Target/ARM/ARMMachObjectWriter.cpp index 4c35d0b..a36e47d 100644 --- a/lib/Target/ARM/ARMMachObjectWriter.cpp +++ b/lib/Target/ARM/ARMMachObjectWriter.cpp @@ -8,19 +8,376 @@ //===----------------------------------------------------------------------===// #include "ARM.h" +#include "ARMFixupKinds.h" +#include "llvm/ADT/Twine.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCAsmLayout.h" #include "llvm/MC/MCMachObjectWriter.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCFixup.h" +#include "llvm/MC/MCFixupKindInfo.h" +#include "llvm/MC/MCValue.h" +#include "llvm/Object/MachOFormat.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Target/TargetAsmBackend.h" using namespace llvm; +using namespace llvm::object; namespace { class ARMMachObjectWriter : public MCMachObjectTargetWriter { + void RecordARMScatteredRelocation(MachObjectWriter *Writer, + const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, + MCValue Target, + unsigned Log2Size, + uint64_t &FixedValue); + void RecordARMMovwMovtRelocation(MachObjectWriter *Writer, + const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, MCValue Target, + uint64_t &FixedValue); + public: ARMMachObjectWriter(bool Is64Bit, uint32_t CPUType, uint32_t CPUSubtype) : MCMachObjectTargetWriter(Is64Bit, CPUType, CPUSubtype, /*UseAggressiveSymbolFolding=*/true) {} + + void RecordRelocation(MachObjectWriter *Writer, + const MCAssembler &Asm, const MCAsmLayout &Layout, + const MCFragment *Fragment, const MCFixup &Fixup, + MCValue Target, uint64_t &FixedValue); }; } +static bool getARMFixupKindMachOInfo(unsigned Kind, unsigned &RelocType, + unsigned &Log2Size) { + RelocType = unsigned(macho::RIT_Vanilla); + Log2Size = ~0U; + + switch (Kind) { + default: + return false; + + case FK_Data_1: + Log2Size = llvm::Log2_32(1); + return true; + case FK_Data_2: + Log2Size = llvm::Log2_32(2); + return true; + case FK_Data_4: + Log2Size = llvm::Log2_32(4); + return true; + case FK_Data_8: + Log2Size = llvm::Log2_32(8); + return true; + + // Handle 24-bit branch kinds. + case ARM::fixup_arm_ldst_pcrel_12: + case ARM::fixup_arm_pcrel_10: + case ARM::fixup_arm_adr_pcrel_12: + case ARM::fixup_arm_condbranch: + case ARM::fixup_arm_uncondbranch: + RelocType = unsigned(macho::RIT_ARM_Branch24Bit); + // Report as 'long', even though that is not quite accurate. + Log2Size = llvm::Log2_32(4); + return true; + + // Handle Thumb branches. + case ARM::fixup_arm_thumb_br: + RelocType = unsigned(macho::RIT_ARM_ThumbBranch22Bit); + Log2Size = llvm::Log2_32(2); + return true; + + case ARM::fixup_t2_uncondbranch: + case ARM::fixup_arm_thumb_bl: + case ARM::fixup_arm_thumb_blx: + RelocType = unsigned(macho::RIT_ARM_ThumbBranch22Bit); + Log2Size = llvm::Log2_32(4); + return true; + + case ARM::fixup_arm_movt_hi16: + case ARM::fixup_arm_movt_hi16_pcrel: + case ARM::fixup_t2_movt_hi16: + case ARM::fixup_t2_movt_hi16_pcrel: + RelocType = unsigned(macho::RIT_ARM_HalfDifference); + // Report as 'long', even though that is not quite accurate. + Log2Size = llvm::Log2_32(4); + return true; + + case ARM::fixup_arm_movw_lo16: + case ARM::fixup_arm_movw_lo16_pcrel: + case ARM::fixup_t2_movw_lo16: + case ARM::fixup_t2_movw_lo16_pcrel: + RelocType = unsigned(macho::RIT_ARM_Half); + // Report as 'long', even though that is not quite accurate. + Log2Size = llvm::Log2_32(4); + return true; + } +} + +void ARMMachObjectWriter:: +RecordARMMovwMovtRelocation(MachObjectWriter *Writer, + const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, + MCValue Target, + uint64_t &FixedValue) { + uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); + unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind()); + unsigned Type = macho::RIT_ARM_Half; + + // See . + const MCSymbol *A = &Target.getSymA()->getSymbol(); + MCSymbolData *A_SD = &Asm.getSymbolData(*A); + + if (!A_SD->getFragment()) + report_fatal_error("symbol '" + A->getName() + + "' can not be undefined in a subtraction expression"); + + uint32_t Value = Writer->getSymbolAddress(A_SD, Layout); + uint32_t Value2 = 0; + uint64_t SecAddr = + Writer->getSectionAddress(A_SD->getFragment()->getParent()); + FixedValue += SecAddr; + + if (const MCSymbolRefExpr *B = Target.getSymB()) { + MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol()); + + if (!B_SD->getFragment()) + report_fatal_error("symbol '" + B->getSymbol().getName() + + "' can not be undefined in a subtraction expression"); + + // Select the appropriate difference relocation type. + Type = macho::RIT_ARM_HalfDifference; + Value2 = Writer->getSymbolAddress(B_SD, Layout); + FixedValue -= Writer->getSectionAddress(B_SD->getFragment()->getParent()); + } + + // Relocations are written out in reverse order, so the PAIR comes first. + // ARM_RELOC_HALF and ARM_RELOC_HALF_SECTDIFF abuse the r_length field: + // + // For these two r_type relocations they always have a pair following them and + // the r_length bits are used differently. The encoding of the r_length is as + // follows: + // low bit of r_length: + // 0 - :lower16: for movw instructions + // 1 - :upper16: for movt instructions + // high bit of r_length: + // 0 - arm instructions + // 1 - thumb instructions + // the other half of the relocated expression is in the following pair + // relocation entry in the the low 16 bits of r_address field. + unsigned ThumbBit = 0; + unsigned MovtBit = 0; + switch ((unsigned)Fixup.getKind()) { + default: break; + case ARM::fixup_arm_movt_hi16: + case ARM::fixup_arm_movt_hi16_pcrel: + MovtBit = 1; + break; + case ARM::fixup_t2_movt_hi16: + case ARM::fixup_t2_movt_hi16_pcrel: + MovtBit = 1; + // Fallthrough + case ARM::fixup_t2_movw_lo16: + case ARM::fixup_t2_movw_lo16_pcrel: + ThumbBit = 1; + break; + } + + + if (Type == macho::RIT_ARM_HalfDifference) { + uint32_t OtherHalf = MovtBit + ? (FixedValue & 0xffff) : ((FixedValue & 0xffff0000) >> 16); + + macho::RelocationEntry MRE; + MRE.Word0 = ((OtherHalf << 0) | + (macho::RIT_Pair << 24) | + (MovtBit << 28) | + (ThumbBit << 29) | + (IsPCRel << 30) | + macho::RF_Scattered); + MRE.Word1 = Value2; + Writer->addRelocation(Fragment->getParent(), MRE); + } + + macho::RelocationEntry MRE; + MRE.Word0 = ((FixupOffset << 0) | + (Type << 24) | + (MovtBit << 28) | + (ThumbBit << 29) | + (IsPCRel << 30) | + macho::RF_Scattered); + MRE.Word1 = Value; + Writer->addRelocation(Fragment->getParent(), MRE); +} + +void ARMMachObjectWriter::RecordARMScatteredRelocation(MachObjectWriter *Writer, + const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, + MCValue Target, + unsigned Log2Size, + uint64_t &FixedValue) { + uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); + unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind()); + unsigned Type = macho::RIT_Vanilla; + + // See . + const MCSymbol *A = &Target.getSymA()->getSymbol(); + MCSymbolData *A_SD = &Asm.getSymbolData(*A); + + if (!A_SD->getFragment()) + report_fatal_error("symbol '" + A->getName() + + "' can not be undefined in a subtraction expression"); + + uint32_t Value = Writer->getSymbolAddress(A_SD, Layout); + uint64_t SecAddr = Writer->getSectionAddress(A_SD->getFragment()->getParent()); + FixedValue += SecAddr; + uint32_t Value2 = 0; + + if (const MCSymbolRefExpr *B = Target.getSymB()) { + MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol()); + + if (!B_SD->getFragment()) + report_fatal_error("symbol '" + B->getSymbol().getName() + + "' can not be undefined in a subtraction expression"); + + // Select the appropriate difference relocation type. + Type = macho::RIT_Difference; + Value2 = Writer->getSymbolAddress(B_SD, Layout); + FixedValue -= Writer->getSectionAddress(B_SD->getFragment()->getParent()); + } + + // Relocations are written out in reverse order, so the PAIR comes first. + if (Type == macho::RIT_Difference || + Type == macho::RIT_Generic_LocalDifference) { + macho::RelocationEntry MRE; + MRE.Word0 = ((0 << 0) | + (macho::RIT_Pair << 24) | + (Log2Size << 28) | + (IsPCRel << 30) | + macho::RF_Scattered); + MRE.Word1 = Value2; + Writer->addRelocation(Fragment->getParent(), MRE); + } + + macho::RelocationEntry MRE; + MRE.Word0 = ((FixupOffset << 0) | + (Type << 24) | + (Log2Size << 28) | + (IsPCRel << 30) | + macho::RF_Scattered); + MRE.Word1 = Value; + Writer->addRelocation(Fragment->getParent(), MRE); +} + +void ARMMachObjectWriter::RecordRelocation(MachObjectWriter *Writer, + const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, + MCValue Target, + uint64_t &FixedValue) { + unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind()); + unsigned Log2Size; + unsigned RelocType = macho::RIT_Vanilla; + if (!getARMFixupKindMachOInfo(Fixup.getKind(), RelocType, Log2Size)) { + report_fatal_error("unknown ARM fixup kind!"); + return; + } + + // If this is a difference or a defined symbol plus an offset, then we need a + // scattered relocation entry. Differences always require scattered + // relocations. + if (Target.getSymB()) { + if (RelocType == macho::RIT_ARM_Half || + RelocType == macho::RIT_ARM_HalfDifference) + return RecordARMMovwMovtRelocation(Writer, Asm, Layout, Fragment, Fixup, + Target, FixedValue); + return RecordARMScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup, + Target, Log2Size, FixedValue); + } + + // Get the symbol data, if any. + MCSymbolData *SD = 0; + if (Target.getSymA()) + SD = &Asm.getSymbolData(Target.getSymA()->getSymbol()); + + // FIXME: For other platforms, we need to use scattered relocations for + // internal relocations with offsets. If this is an internal relocation with + // an offset, it also needs a scattered relocation entry. + // + // Is this right for ARM? + uint32_t Offset = Target.getConstant(); + if (IsPCRel && RelocType == macho::RIT_Vanilla) + Offset += 1 << Log2Size; + if (Offset && SD && !Writer->doesSymbolRequireExternRelocation(SD)) + return RecordARMScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup, + Target, Log2Size, FixedValue); + + // See . + uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); + unsigned Index = 0; + unsigned IsExtern = 0; + unsigned Type = 0; + + if (Target.isAbsolute()) { // constant + // FIXME! + report_fatal_error("FIXME: relocations to absolute targets " + "not yet implemented"); + } else { + // Resolve constant variables. + if (SD->getSymbol().isVariable()) { + int64_t Res; + if (SD->getSymbol().getVariableValue()->EvaluateAsAbsolute( + Res, Layout, Writer->getSectionAddressMap())) { + FixedValue = Res; + return; + } + } + + // Check whether we need an external or internal relocation. + if (Writer->doesSymbolRequireExternRelocation(SD)) { + IsExtern = 1; + Index = SD->getIndex(); + + // For external relocations, make sure to offset the fixup value to + // compensate for the addend of the symbol address, if it was + // undefined. This occurs with weak definitions, for example. + if (!SD->Symbol->isUndefined()) + FixedValue -= Layout.getSymbolOffset(SD); + } else { + // The index is the section ordinal (1-based). + const MCSectionData &SymSD = Asm.getSectionData( + SD->getSymbol().getSection()); + Index = SymSD.getOrdinal() + 1; + FixedValue += Writer->getSectionAddress(&SymSD); + } + if (IsPCRel) + FixedValue -= Writer->getSectionAddress(Fragment->getParent()); + + // The type is determined by the fixup kind. + Type = RelocType; + } + + // struct relocation_info (8 bytes) + macho::RelocationEntry MRE; + MRE.Word0 = FixupOffset; + MRE.Word1 = ((Index << 0) | + (IsPCRel << 24) | + (Log2Size << 25) | + (IsExtern << 27) | + (Type << 28)); + Writer->addRelocation(Fragment->getParent(), MRE); +} + MCObjectWriter *llvm::createARMMachObjectWriter(raw_ostream &OS, bool Is64Bit, uint32_t CPUType, diff --git a/lib/Target/PowerPC/PPCAsmBackend.cpp b/lib/Target/PowerPC/PPCAsmBackend.cpp index f562a3f..4b8cbb7 100644 --- a/lib/Target/PowerPC/PPCAsmBackend.cpp +++ b/lib/Target/PowerPC/PPCAsmBackend.cpp @@ -13,6 +13,7 @@ #include "llvm/MC/MCMachObjectWriter.h" #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCObjectWriter.h" +#include "llvm/MC/MCValue.h" #include "llvm/Object/MachOFormat.h" #include "llvm/Target/TargetRegistry.h" using namespace llvm; @@ -23,6 +24,11 @@ public: PPCMachObjectWriter(bool Is64Bit, uint32_t CPUType, uint32_t CPUSubtype) : MCMachObjectTargetWriter(Is64Bit, CPUType, CPUSubtype) {} + + void RecordRelocation(MachObjectWriter *Writer, + const MCAssembler &Asm, const MCAsmLayout &Layout, + const MCFragment *Fragment, const MCFixup &Fixup, + MCValue Target, uint64_t &FixedValue) {} }; class PPCAsmBackend : public TargetAsmBackend { diff --git a/lib/Target/X86/X86MachObjectWriter.cpp b/lib/Target/X86/X86MachObjectWriter.cpp index 8f3dd32..3711038 100644 --- a/lib/Target/X86/X86MachObjectWriter.cpp +++ b/lib/Target/X86/X86MachObjectWriter.cpp @@ -8,19 +8,541 @@ //===----------------------------------------------------------------------===// #include "X86.h" +#include "X86FixupKinds.h" +#include "llvm/ADT/Twine.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCAsmLayout.h" #include "llvm/MC/MCMachObjectWriter.h" +#include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCValue.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Object/MachOFormat.h" + using namespace llvm; +using namespace llvm::object; namespace { class X86MachObjectWriter : public MCMachObjectTargetWriter { + void RecordScatteredRelocation(MachObjectWriter *Writer, + const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, + MCValue Target, + unsigned Log2Size, + uint64_t &FixedValue); + void RecordTLVPRelocation(MachObjectWriter *Writer, + const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, + MCValue Target, + uint64_t &FixedValue); + + void RecordX86Relocation(MachObjectWriter *Writer, + const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, + MCValue Target, + uint64_t &FixedValue); + void RecordX86_64Relocation(MachObjectWriter *Writer, + const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, + MCValue Target, + uint64_t &FixedValue); public: X86MachObjectWriter(bool Is64Bit, uint32_t CPUType, uint32_t CPUSubtype) : MCMachObjectTargetWriter(Is64Bit, CPUType, CPUSubtype, /*UseAggressiveSymbolFolding=*/Is64Bit) {} + + void RecordRelocation(MachObjectWriter *Writer, + const MCAssembler &Asm, const MCAsmLayout &Layout, + const MCFragment *Fragment, const MCFixup &Fixup, + MCValue Target, uint64_t &FixedValue) { + if (Writer->is64Bit()) + RecordX86_64Relocation(Writer, Asm, Layout, Fragment, Fixup, Target, + FixedValue); + else + RecordX86Relocation(Writer, Asm, Layout, Fragment, Fixup, Target, + FixedValue); + } }; } +static bool isFixupKindRIPRel(unsigned Kind) { + return Kind == X86::reloc_riprel_4byte || + Kind == X86::reloc_riprel_4byte_movq_load; +} + +static unsigned getFixupKindLog2Size(unsigned Kind) { + switch (Kind) { + default: + llvm_unreachable("invalid fixup kind!"); + case FK_PCRel_1: + case FK_Data_1: return 0; + case FK_PCRel_2: + case FK_Data_2: return 1; + case FK_PCRel_4: + // FIXME: Remove these!!! + case X86::reloc_riprel_4byte: + case X86::reloc_riprel_4byte_movq_load: + case X86::reloc_signed_4byte: + case FK_Data_4: return 2; + case FK_Data_8: return 3; + } +} + +void X86MachObjectWriter::RecordX86_64Relocation(MachObjectWriter *Writer, + const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, + MCValue Target, + uint64_t &FixedValue) { + unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind()); + unsigned IsRIPRel = isFixupKindRIPRel(Fixup.getKind()); + unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind()); + + // See . + uint32_t FixupOffset = + Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); + uint32_t FixupAddress = + Writer->getFragmentAddress(Fragment, Layout) + Fixup.getOffset(); + int64_t Value = 0; + unsigned Index = 0; + unsigned IsExtern = 0; + unsigned Type = 0; + + Value = Target.getConstant(); + + if (IsPCRel) { + // Compensate for the relocation offset, Darwin x86_64 relocations only have + // the addend and appear to have attempted to define it to be the actual + // expression addend without the PCrel bias. However, instructions with data + // following the relocation are not accommodated for (see comment below + // regarding SIGNED{1,2,4}), so it isn't exactly that either. + Value += 1LL << Log2Size; + } + + if (Target.isAbsolute()) { // constant + // SymbolNum of 0 indicates the absolute section. + Type = macho::RIT_X86_64_Unsigned; + Index = 0; + + // FIXME: I believe this is broken, I don't think the linker can understand + // it. I think it would require a local relocation, but I'm not sure if that + // would work either. The official way to get an absolute PCrel relocation + // is to use an absolute symbol (which we don't support yet). + if (IsPCRel) { + IsExtern = 1; + Type = macho::RIT_X86_64_Branch; + } + } else if (Target.getSymB()) { // A - B + constant + const MCSymbol *A = &Target.getSymA()->getSymbol(); + MCSymbolData &A_SD = Asm.getSymbolData(*A); + const MCSymbolData *A_Base = Asm.getAtom(&A_SD); + + const MCSymbol *B = &Target.getSymB()->getSymbol(); + MCSymbolData &B_SD = Asm.getSymbolData(*B); + const MCSymbolData *B_Base = Asm.getAtom(&B_SD); + + // Neither symbol can be modified. + if (Target.getSymA()->getKind() != MCSymbolRefExpr::VK_None || + Target.getSymB()->getKind() != MCSymbolRefExpr::VK_None) + report_fatal_error("unsupported relocation of modified symbol"); + + // We don't support PCrel relocations of differences. Darwin 'as' doesn't + // implement most of these correctly. + if (IsPCRel) + report_fatal_error("unsupported pc-relative relocation of difference"); + + // The support for the situation where one or both of the symbols would + // require a local relocation is handled just like if the symbols were + // external. This is certainly used in the case of debug sections where the + // section has only temporary symbols and thus the symbols don't have base + // symbols. This is encoded using the section ordinal and non-extern + // relocation entries. + + // Darwin 'as' doesn't emit correct relocations for this (it ends up with a + // single SIGNED relocation); reject it for now. Except the case where both + // symbols don't have a base, equal but both NULL. + if (A_Base == B_Base && A_Base) + report_fatal_error("unsupported relocation with identical base"); + + Value += Writer->getSymbolAddress(&A_SD, Layout) - + (A_Base == NULL ? 0 : Writer->getSymbolAddress(A_Base, Layout)); + Value -= Writer->getSymbolAddress(&B_SD, Layout) - + (B_Base == NULL ? 0 : Writer->getSymbolAddress(B_Base, Layout)); + + if (A_Base) { + Index = A_Base->getIndex(); + IsExtern = 1; + } + else { + Index = A_SD.getFragment()->getParent()->getOrdinal() + 1; + IsExtern = 0; + } + Type = macho::RIT_X86_64_Unsigned; + + macho::RelocationEntry MRE; + MRE.Word0 = FixupOffset; + MRE.Word1 = ((Index << 0) | + (IsPCRel << 24) | + (Log2Size << 25) | + (IsExtern << 27) | + (Type << 28)); + Writer->addRelocation(Fragment->getParent(), MRE); + + if (B_Base) { + Index = B_Base->getIndex(); + IsExtern = 1; + } + else { + Index = B_SD.getFragment()->getParent()->getOrdinal() + 1; + IsExtern = 0; + } + Type = macho::RIT_X86_64_Subtractor; + } else { + const MCSymbol *Symbol = &Target.getSymA()->getSymbol(); + MCSymbolData &SD = Asm.getSymbolData(*Symbol); + const MCSymbolData *Base = Asm.getAtom(&SD); + + // Relocations inside debug sections always use local relocations when + // possible. This seems to be done because the debugger doesn't fully + // understand x86_64 relocation entries, and expects to find values that + // have already been fixed up. + if (Symbol->isInSection()) { + const MCSectionMachO &Section = static_cast( + Fragment->getParent()->getSection()); + if (Section.hasAttribute(MCSectionMachO::S_ATTR_DEBUG)) + Base = 0; + } + + // x86_64 almost always uses external relocations, except when there is no + // symbol to use as a base address (a local symbol with no preceding + // non-local symbol). + if (Base) { + Index = Base->getIndex(); + IsExtern = 1; + + // Add the local offset, if needed. + if (Base != &SD) + Value += Layout.getSymbolOffset(&SD) - Layout.getSymbolOffset(Base); + } else if (Symbol->isInSection() && !Symbol->isVariable()) { + // The index is the section ordinal (1-based). + Index = SD.getFragment()->getParent()->getOrdinal() + 1; + IsExtern = 0; + Value += Writer->getSymbolAddress(&SD, Layout); + + if (IsPCRel) + Value -= FixupAddress + (1 << Log2Size); + } else if (Symbol->isVariable()) { + const MCExpr *Value = Symbol->getVariableValue(); + int64_t Res; + bool isAbs = Value->EvaluateAsAbsolute(Res, Layout, + Writer->getSectionAddressMap()); + if (isAbs) { + FixedValue = Res; + return; + } else { + report_fatal_error("unsupported relocation of variable '" + + Symbol->getName() + "'"); + } + } else { + report_fatal_error("unsupported relocation of undefined symbol '" + + Symbol->getName() + "'"); + } + + MCSymbolRefExpr::VariantKind Modifier = Target.getSymA()->getKind(); + if (IsPCRel) { + if (IsRIPRel) { + if (Modifier == MCSymbolRefExpr::VK_GOTPCREL) { + // x86_64 distinguishes movq foo@GOTPCREL so that the linker can + // rewrite the movq to an leaq at link time if the symbol ends up in + // the same linkage unit. + if (unsigned(Fixup.getKind()) == X86::reloc_riprel_4byte_movq_load) + Type = macho::RIT_X86_64_GOTLoad; + else + Type = macho::RIT_X86_64_GOT; + } else if (Modifier == MCSymbolRefExpr::VK_TLVP) { + Type = macho::RIT_X86_64_TLV; + } else if (Modifier != MCSymbolRefExpr::VK_None) { + report_fatal_error("unsupported symbol modifier in relocation"); + } else { + Type = macho::RIT_X86_64_Signed; + + // The Darwin x86_64 relocation format has a problem where it cannot + // encode an address (L + ) which is outside the atom + // containing L. Generally, this shouldn't occur but it does + // happen when we have a RIPrel instruction with data following the + // relocation entry (e.g., movb $012, L0(%rip)). Even with the PCrel + // adjustment Darwin x86_64 uses, the offset is still negative and the + // linker has no way to recognize this. + // + // To work around this, Darwin uses several special relocation types + // to indicate the offsets. However, the specification or + // implementation of these seems to also be incomplete; they should + // adjust the addend as well based on the actual encoded instruction + // (the additional bias), but instead appear to just look at the final + // offset. + switch (-(Target.getConstant() + (1LL << Log2Size))) { + case 1: Type = macho::RIT_X86_64_Signed1; break; + case 2: Type = macho::RIT_X86_64_Signed2; break; + case 4: Type = macho::RIT_X86_64_Signed4; break; + } + } + } else { + if (Modifier != MCSymbolRefExpr::VK_None) + report_fatal_error("unsupported symbol modifier in branch " + "relocation"); + + Type = macho::RIT_X86_64_Branch; + } + } else { + if (Modifier == MCSymbolRefExpr::VK_GOT) { + Type = macho::RIT_X86_64_GOT; + } else if (Modifier == MCSymbolRefExpr::VK_GOTPCREL) { + // GOTPCREL is allowed as a modifier on non-PCrel instructions, in which + // case all we do is set the PCrel bit in the relocation entry; this is + // used with exception handling, for example. The source is required to + // include any necessary offset directly. + Type = macho::RIT_X86_64_GOT; + IsPCRel = 1; + } else if (Modifier == MCSymbolRefExpr::VK_TLVP) { + report_fatal_error("TLVP symbol modifier should have been rip-rel"); + } else if (Modifier != MCSymbolRefExpr::VK_None) + report_fatal_error("unsupported symbol modifier in relocation"); + else + Type = macho::RIT_X86_64_Unsigned; + } + } + + // x86_64 always writes custom values into the fixups. + FixedValue = Value; + + // struct relocation_info (8 bytes) + macho::RelocationEntry MRE; + MRE.Word0 = FixupOffset; + MRE.Word1 = ((Index << 0) | + (IsPCRel << 24) | + (Log2Size << 25) | + (IsExtern << 27) | + (Type << 28)); + Writer->addRelocation(Fragment->getParent(), MRE); +} + +void X86MachObjectWriter::RecordScatteredRelocation(MachObjectWriter *Writer, + const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, + MCValue Target, + unsigned Log2Size, + uint64_t &FixedValue) { + uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); + unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind()); + unsigned Type = macho::RIT_Vanilla; + + // See . + const MCSymbol *A = &Target.getSymA()->getSymbol(); + MCSymbolData *A_SD = &Asm.getSymbolData(*A); + + if (!A_SD->getFragment()) + report_fatal_error("symbol '" + A->getName() + + "' can not be undefined in a subtraction expression"); + + uint32_t Value = Writer->getSymbolAddress(A_SD, Layout); + uint64_t SecAddr = Writer->getSectionAddress(A_SD->getFragment()->getParent()); + FixedValue += SecAddr; + uint32_t Value2 = 0; + + if (const MCSymbolRefExpr *B = Target.getSymB()) { + MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol()); + + if (!B_SD->getFragment()) + report_fatal_error("symbol '" + B->getSymbol().getName() + + "' can not be undefined in a subtraction expression"); + + // Select the appropriate difference relocation type. + // + // Note that there is no longer any semantic difference between these two + // relocation types from the linkers point of view, this is done solely for + // pedantic compatibility with 'as'. + Type = A_SD->isExternal() ? (unsigned)macho::RIT_Difference : + (unsigned)macho::RIT_Generic_LocalDifference; + Value2 = Writer->getSymbolAddress(B_SD, Layout); + FixedValue -= Writer->getSectionAddress(B_SD->getFragment()->getParent()); + } + + // Relocations are written out in reverse order, so the PAIR comes first. + if (Type == macho::RIT_Difference || + Type == macho::RIT_Generic_LocalDifference) { + macho::RelocationEntry MRE; + MRE.Word0 = ((0 << 0) | + (macho::RIT_Pair << 24) | + (Log2Size << 28) | + (IsPCRel << 30) | + macho::RF_Scattered); + MRE.Word1 = Value2; + Writer->addRelocation(Fragment->getParent(), MRE); + } + + macho::RelocationEntry MRE; + MRE.Word0 = ((FixupOffset << 0) | + (Type << 24) | + (Log2Size << 28) | + (IsPCRel << 30) | + macho::RF_Scattered); + MRE.Word1 = Value; + Writer->addRelocation(Fragment->getParent(), MRE); +} + +void X86MachObjectWriter::RecordTLVPRelocation(MachObjectWriter *Writer, + const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, + MCValue Target, + uint64_t &FixedValue) { + assert(Target.getSymA()->getKind() == MCSymbolRefExpr::VK_TLVP && + !is64Bit() && + "Should only be called with a 32-bit TLVP relocation!"); + + unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind()); + uint32_t Value = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); + unsigned IsPCRel = 0; + + // Get the symbol data. + MCSymbolData *SD_A = &Asm.getSymbolData(Target.getSymA()->getSymbol()); + unsigned Index = SD_A->getIndex(); + + // We're only going to have a second symbol in pic mode and it'll be a + // subtraction from the picbase. For 32-bit pic the addend is the difference + // between the picbase and the next address. For 32-bit static the addend is + // zero. + if (Target.getSymB()) { + // If this is a subtraction then we're pcrel. + uint32_t FixupAddress = + Writer->getFragmentAddress(Fragment, Layout) + Fixup.getOffset(); + MCSymbolData *SD_B = &Asm.getSymbolData(Target.getSymB()->getSymbol()); + IsPCRel = 1; + FixedValue = (FixupAddress - Writer->getSymbolAddress(SD_B, Layout) + + Target.getConstant()); + FixedValue += 1ULL << Log2Size; + } else { + FixedValue = 0; + } + + // struct relocation_info (8 bytes) + macho::RelocationEntry MRE; + MRE.Word0 = Value; + MRE.Word1 = ((Index << 0) | + (IsPCRel << 24) | + (Log2Size << 25) | + (1 << 27) | // Extern + (macho::RIT_Generic_TLV << 28)); // Type + Writer->addRelocation(Fragment->getParent(), MRE); +} + +void X86MachObjectWriter::RecordX86Relocation(MachObjectWriter *Writer, + const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, + MCValue Target, + uint64_t &FixedValue) { + unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind()); + unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind()); + + // If this is a 32-bit TLVP reloc it's handled a bit differently. + if (Target.getSymA() && + Target.getSymA()->getKind() == MCSymbolRefExpr::VK_TLVP) { + RecordTLVPRelocation(Writer, Asm, Layout, Fragment, Fixup, Target, + FixedValue); + return; + } + + // If this is a difference or a defined symbol plus an offset, then we need a + // scattered relocation entry. Differences always require scattered + // relocations. + if (Target.getSymB()) + return RecordScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup, + Target, Log2Size, FixedValue); + + // Get the symbol data, if any. + MCSymbolData *SD = 0; + if (Target.getSymA()) + SD = &Asm.getSymbolData(Target.getSymA()->getSymbol()); + + // If this is an internal relocation with an offset, it also needs a scattered + // relocation entry. + uint32_t Offset = Target.getConstant(); + if (IsPCRel) + Offset += 1 << Log2Size; + if (Offset && SD && !Writer->doesSymbolRequireExternRelocation(SD)) + return RecordScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup, + Target, Log2Size, FixedValue); + + // See . + uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); + unsigned Index = 0; + unsigned IsExtern = 0; + unsigned Type = 0; + + if (Target.isAbsolute()) { // constant + // SymbolNum of 0 indicates the absolute section. + // + // FIXME: Currently, these are never generated (see code below). I cannot + // find a case where they are actually emitted. + Type = macho::RIT_Vanilla; + } else { + // Resolve constant variables. + if (SD->getSymbol().isVariable()) { + int64_t Res; + if (SD->getSymbol().getVariableValue()->EvaluateAsAbsolute( + Res, Layout, Writer->getSectionAddressMap())) { + FixedValue = Res; + return; + } + } + + // Check whether we need an external or internal relocation. + if (Writer->doesSymbolRequireExternRelocation(SD)) { + IsExtern = 1; + Index = SD->getIndex(); + // For external relocations, make sure to offset the fixup value to + // compensate for the addend of the symbol address, if it was + // undefined. This occurs with weak definitions, for example. + if (!SD->Symbol->isUndefined()) + FixedValue -= Layout.getSymbolOffset(SD); + } else { + // The index is the section ordinal (1-based). + const MCSectionData &SymSD = Asm.getSectionData( + SD->getSymbol().getSection()); + Index = SymSD.getOrdinal() + 1; + FixedValue += Writer->getSectionAddress(&SymSD); + } + if (IsPCRel) + FixedValue -= Writer->getSectionAddress(Fragment->getParent()); + + Type = macho::RIT_Vanilla; + } + + // struct relocation_info (8 bytes) + macho::RelocationEntry MRE; + MRE.Word0 = FixupOffset; + MRE.Word1 = ((Index << 0) | + (IsPCRel << 24) | + (Log2Size << 25) | + (IsExtern << 27) | + (Type << 28)); + Writer->addRelocation(Fragment->getParent(), MRE); +} + MCObjectWriter *llvm::createX86MachObjectWriter(raw_ostream &OS, bool Is64Bit, uint32_t CPUType, -- cgit v1.1 From 5e6b4605bd620a864055276a6d454e5a18f9fee8 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Fri, 24 Jun 2011 23:44:48 +0000 Subject: Rename TargetRegisterDesc to MCRegisterDesc git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133845 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/MC/MCRegisterInfo.h | 4 ++-- include/llvm/Target/TargetRegisterInfo.h | 3 --- utils/TableGen/RegisterInfoEmitter.cpp | 4 ++-- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/include/llvm/MC/MCRegisterInfo.h b/include/llvm/MC/MCRegisterInfo.h index c2ec08e..7b16e7b 100644 --- a/include/llvm/MC/MCRegisterInfo.h +++ b/include/llvm/MC/MCRegisterInfo.h @@ -20,7 +20,7 @@ namespace llvm { -/// TargetRegisterDesc - This record contains all of the information known about +/// MCRegisterDesc - This record contains all of the information known about /// a particular register. The Overlaps field contains a pointer to a zero /// terminated array of registers that this register aliases, starting with /// itself. This is needed for architectures like X86 which have AL alias AX @@ -38,7 +38,7 @@ struct MCRegisterDesc { }; /// MCRegisterInfo base class - We assume that the target defines a static -/// array of TargetRegisterDesc objects that represent all of the machine +/// array of MCRegisterDesc objects that represent all of the machine /// registers that the target has. As such, we simply have to track a pointer /// to this array so that we can turn register number into a register /// descriptor. diff --git a/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h index 2b7e1f9..d50bfe7 100644 --- a/include/llvm/Target/TargetRegisterInfo.h +++ b/include/llvm/Target/TargetRegisterInfo.h @@ -256,9 +256,6 @@ public: bool isAllocatable() const { return Allocatable; } }; -/// TargetRegisterDesc - It's just an alias of MCRegisterDesc. -typedef MCRegisterDesc TargetRegisterDesc; - /// TargetRegisterInfoDesc - Extra information, not in MCRegisterDesc, about /// registers. These are used by codegen, not by MC. struct TargetRegisterInfoDesc { diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp index 6fd8bb4..9a1db97 100644 --- a/utils/TableGen/RegisterInfoEmitter.cpp +++ b/utils/TableGen/RegisterInfoEmitter.cpp @@ -79,7 +79,7 @@ void RegisterInfoEmitter::runHeader(raw_ostream &OS) { OS << "struct " << ClassName << " : public TargetRegisterInfo {\n" << " explicit " << ClassName - << "(const TargetRegisterDesc *D, const TargetRegisterInfoDesc *ID, " + << "(const MCRegisterDesc *D, const TargetRegisterInfoDesc *ID, " << "int CallFrameSetupOpcode = -1, int CallFrameDestroyOpcode = -1);\n" << " virtual int getDwarfRegNumFull(unsigned RegNum, " << "unsigned Flavour) const;\n" @@ -518,7 +518,7 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { // Emit the constructor of the class... OS << ClassName << "::" << ClassName - << "(const TargetRegisterDesc *D, const TargetRegisterInfoDesc *ID, " + << "(const MCRegisterDesc *D, const TargetRegisterInfoDesc *ID, " << "int CallFrameSetupOpcode, int CallFrameDestroyOpcode)\n" << " : TargetRegisterInfo(ID" << ", RegisterClasses, RegisterClasses+" << RegisterClasses.size() <<",\n" -- cgit v1.1 From 46af0d73412aa566745e8c6808c299f0c6f3b245 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Fri, 24 Jun 2011 23:53:19 +0000 Subject: Rename TargetDesc to MCTargetDesc git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133846 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/CMakeLists.txt | 1 + lib/Target/X86/MCTargetDesc/Makefile | 16 +++++++++++++ lib/Target/X86/MCTargetDesc/X86TargetDesc.cpp | 33 +++++++++++++++++++++++++++ lib/Target/X86/MCTargetDesc/X86TargetDesc.h | 23 +++++++++++++++++++ lib/Target/X86/Makefile | 2 +- lib/Target/X86/TargetDesc/Makefile | 16 ------------- lib/Target/X86/TargetDesc/X86TargetDesc.cpp | 33 --------------------------- lib/Target/X86/TargetDesc/X86TargetDesc.h | 23 ------------------- lib/Target/X86/X86.h | 4 +--- 9 files changed, 75 insertions(+), 76 deletions(-) create mode 100644 lib/Target/X86/MCTargetDesc/Makefile create mode 100644 lib/Target/X86/MCTargetDesc/X86TargetDesc.cpp create mode 100644 lib/Target/X86/MCTargetDesc/X86TargetDesc.h delete mode 100644 lib/Target/X86/TargetDesc/Makefile delete mode 100644 lib/Target/X86/TargetDesc/X86TargetDesc.cpp delete mode 100644 lib/Target/X86/TargetDesc/X86TargetDesc.h diff --git a/lib/Target/X86/CMakeLists.txt b/lib/Target/X86/CMakeLists.txt index 5e0c84f..7237ed8 100644 --- a/lib/Target/X86/CMakeLists.txt +++ b/lib/Target/X86/CMakeLists.txt @@ -61,5 +61,6 @@ add_llvm_target(X86CodeGen ${sources}) add_subdirectory(AsmParser) add_subdirectory(Disassembler) add_subdirectory(InstPrinter) +add_subdirectory(MCTargetDesc) add_subdirectory(TargetInfo) add_subdirectory(Utils) diff --git a/lib/Target/X86/MCTargetDesc/Makefile b/lib/Target/X86/MCTargetDesc/Makefile new file mode 100644 index 0000000..b19774e --- /dev/null +++ b/lib/Target/X86/MCTargetDesc/Makefile @@ -0,0 +1,16 @@ +##===- lib/Target/X86/TargetDesc/Makefile ------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../../.. +LIBRARYNAME = LLVMX86Desc + +# Hack: we need to include 'main' target directory to grab private headers +CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common diff --git a/lib/Target/X86/MCTargetDesc/X86TargetDesc.cpp b/lib/Target/X86/MCTargetDesc/X86TargetDesc.cpp new file mode 100644 index 0000000..8d61745 --- /dev/null +++ b/lib/Target/X86/MCTargetDesc/X86TargetDesc.cpp @@ -0,0 +1,33 @@ +//===-- X86TargetDesc.cpp - X86 Target Descriptions -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides X86 specific target descriptions. +// +//===----------------------------------------------------------------------===// + +#include "X86TargetDesc.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/Target/TargetRegistry.h" +#include "X86GenRegisterDesc.inc" +using namespace llvm; + +MCRegisterInfo *createX86MCRegisterInfo() { + MCRegisterInfo *X = new MCRegisterInfo(); + InitX86MCRegisterInfo(X); + return X; +} + +// Force static initialization. +extern "C" void LLVMInitializeX86MCRegInfo() { + RegisterMCRegInfo X(TheX86_32Target); + RegisterMCRegInfo Y(TheX86_64Target); + + TargetRegistry::RegisterMCRegInfo(TheX86_32Target, createX86MCRegisterInfo); + TargetRegistry::RegisterMCRegInfo(TheX86_64Target, createX86MCRegisterInfo); +} diff --git a/lib/Target/X86/MCTargetDesc/X86TargetDesc.h b/lib/Target/X86/MCTargetDesc/X86TargetDesc.h new file mode 100644 index 0000000..d31f301 --- /dev/null +++ b/lib/Target/X86/MCTargetDesc/X86TargetDesc.h @@ -0,0 +1,23 @@ +//===-- X86TargetDesc.h - X86 Target Descriptions ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides X86 specific target descriptions. +// +//===----------------------------------------------------------------------===// + +namespace llvm { +class Target; + +extern Target TheX86_32Target, TheX86_64Target; +} // End llvm namespace + +// Defines symbolic names for X86 registers. This defines a mapping from +// register name to register number. +// +#include "X86GenRegisterNames.inc" diff --git a/lib/Target/X86/Makefile b/lib/Target/X86/Makefile index 9cd17ee..2102db7 100644 --- a/lib/Target/X86/Makefile +++ b/lib/Target/X86/Makefile @@ -21,6 +21,6 @@ BUILT_SOURCES = X86GenRegisterNames.inc X86GenRegisterDesc.inc \ X86GenCallingConv.inc X86GenSubtarget.inc \ X86GenEDInfo.inc -DIRS = InstPrinter AsmParser Disassembler TargetInfo TargetDesc Utils +DIRS = InstPrinter AsmParser Disassembler TargetInfo MCTargetDesc Utils include $(LEVEL)/Makefile.common diff --git a/lib/Target/X86/TargetDesc/Makefile b/lib/Target/X86/TargetDesc/Makefile deleted file mode 100644 index b19774e..0000000 --- a/lib/Target/X86/TargetDesc/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===- lib/Target/X86/TargetDesc/Makefile ------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -LIBRARYNAME = LLVMX86Desc - -# Hack: we need to include 'main' target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/lib/Target/X86/TargetDesc/X86TargetDesc.cpp b/lib/Target/X86/TargetDesc/X86TargetDesc.cpp deleted file mode 100644 index 8d61745..0000000 --- a/lib/Target/X86/TargetDesc/X86TargetDesc.cpp +++ /dev/null @@ -1,33 +0,0 @@ -//===-- X86TargetDesc.cpp - X86 Target Descriptions -------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file provides X86 specific target descriptions. -// -//===----------------------------------------------------------------------===// - -#include "X86TargetDesc.h" -#include "llvm/MC/MCRegisterInfo.h" -#include "llvm/Target/TargetRegistry.h" -#include "X86GenRegisterDesc.inc" -using namespace llvm; - -MCRegisterInfo *createX86MCRegisterInfo() { - MCRegisterInfo *X = new MCRegisterInfo(); - InitX86MCRegisterInfo(X); - return X; -} - -// Force static initialization. -extern "C" void LLVMInitializeX86MCRegInfo() { - RegisterMCRegInfo X(TheX86_32Target); - RegisterMCRegInfo Y(TheX86_64Target); - - TargetRegistry::RegisterMCRegInfo(TheX86_32Target, createX86MCRegisterInfo); - TargetRegistry::RegisterMCRegInfo(TheX86_64Target, createX86MCRegisterInfo); -} diff --git a/lib/Target/X86/TargetDesc/X86TargetDesc.h b/lib/Target/X86/TargetDesc/X86TargetDesc.h deleted file mode 100644 index d31f301..0000000 --- a/lib/Target/X86/TargetDesc/X86TargetDesc.h +++ /dev/null @@ -1,23 +0,0 @@ -//===-- X86TargetDesc.h - X86 Target Descriptions ---------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file provides X86 specific target descriptions. -// -//===----------------------------------------------------------------------===// - -namespace llvm { -class Target; - -extern Target TheX86_32Target, TheX86_64Target; -} // End llvm namespace - -// Defines symbolic names for X86 registers. This defines a mapping from -// register name to register number. -// -#include "X86GenRegisterNames.inc" diff --git a/lib/Target/X86/X86.h b/lib/Target/X86/X86.h index ec78d48..896bf0a 100644 --- a/lib/Target/X86/X86.h +++ b/lib/Target/X86/X86.h @@ -84,11 +84,9 @@ MCObjectWriter *createX86MachObjectWriter(raw_ostream &OS, uint32_t CPUType, uint32_t CPUSubtype); -extern Target TheX86_32Target, TheX86_64Target; - } // End llvm namespace -#include "TargetDesc/X86TargetDesc.h" +#include "MCTargetDesc/X86TargetDesc.h" // Defines symbolic names for the X86 instructions. // -- cgit v1.1 From 4219718180f3588653334c74dd9ba0d5994b4937 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Fri, 24 Jun 2011 23:59:54 +0000 Subject: Add include guard. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133847 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/MCTargetDesc/X86TargetDesc.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/Target/X86/MCTargetDesc/X86TargetDesc.h b/lib/Target/X86/MCTargetDesc/X86TargetDesc.h index d31f301..bcf851f 100644 --- a/lib/Target/X86/MCTargetDesc/X86TargetDesc.h +++ b/lib/Target/X86/MCTargetDesc/X86TargetDesc.h @@ -11,6 +11,9 @@ // //===----------------------------------------------------------------------===// +#ifndef X86TARGETDESC_H +#define X86TARGETDESC_H + namespace llvm { class Target; @@ -21,3 +24,5 @@ extern Target TheX86_32Target, TheX86_64Target; // register name to register number. // #include "X86GenRegisterNames.inc" + +#endif -- cgit v1.1 From 025b37b5f035fcc9388d9615f6401ab3095d8b3f Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Sat, 25 Jun 2011 00:27:17 +0000 Subject: Remove dead typedefs. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133851 91177308-0d34-0410-b5e6-96231b3b80d8 --- utils/TableGen/RegisterInfoEmitter.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp index 9a1db97..2fcb2d4 100644 --- a/utils/TableGen/RegisterInfoEmitter.cpp +++ b/utils/TableGen/RegisterInfoEmitter.cpp @@ -131,9 +131,6 @@ void RegisterInfoEmitter::runHeader(raw_ostream &OS) { OS << "} // End llvm namespace \n"; } -typedef std::pair UUPair; -typedef std::vector UUVector; - // // RegisterInfoEmitter::run - Main register file description emitter. // -- cgit v1.1 From ba3dc107023a45b4ea027526b4a3434c4db3daad Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Sat, 25 Jun 2011 00:51:50 +0000 Subject: Unbreak CMake build git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133853 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/MCTargetDesc/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 lib/Target/X86/MCTargetDesc/CMakeLists.txt diff --git a/lib/Target/X86/MCTargetDesc/CMakeLists.txt b/lib/Target/X86/MCTargetDesc/CMakeLists.txt new file mode 100644 index 0000000..50be61c --- /dev/null +++ b/lib/Target/X86/MCTargetDesc/CMakeLists.txt @@ -0,0 +1,2 @@ +add_llvm_library(LLVMX86Desc X86TargetDesc.cpp) + -- cgit v1.1 From 75c2b2028bd898cb8448fcf0fa76c3d47843a164 Mon Sep 17 00:00:00 2001 From: Jim Grosbach Date: Sat, 25 Jun 2011 01:53:17 +0000 Subject: Move ARM-specific test to ARM directory. Hopefully make the x86-target-only Windows bots happy. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133856 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/MC/ARM/thumb2-movt-fixup.s | 17 +++++++++++++++++ test/MC/MachO/thumb2-movt-fixup.s | 17 ----------------- 2 files changed, 17 insertions(+), 17 deletions(-) create mode 100644 test/MC/ARM/thumb2-movt-fixup.s delete mode 100644 test/MC/MachO/thumb2-movt-fixup.s diff --git a/test/MC/ARM/thumb2-movt-fixup.s b/test/MC/ARM/thumb2-movt-fixup.s new file mode 100644 index 0000000..ddd95b5 --- /dev/null +++ b/test/MC/ARM/thumb2-movt-fixup.s @@ -0,0 +1,17 @@ +@ RUN: llvm-mc -mcpu=cortex-a8 -triple thumbv7-apple-darwin10 -filetype=obj -o - < %s | macho-dump | FileCheck %s + +_fred: + movt r3, :upper16:(_wilma-(LPC0_0+4)) +LPC0_0: + +_wilma: + .long 0 + +@ CHECK: ('_relocations', [ +@ CHECK: # Relocation 0 +@ CHECK: (('word-0', 0xb9000000), +@ CHECK: ('word-1', 0x4)), +@ CHECK: # Relocation 1 +@ CHECK: (('word-0', 0xb100fffc), +@ CHECK: ('word-1', 0x4)), + diff --git a/test/MC/MachO/thumb2-movt-fixup.s b/test/MC/MachO/thumb2-movt-fixup.s deleted file mode 100644 index ddd95b5..0000000 --- a/test/MC/MachO/thumb2-movt-fixup.s +++ /dev/null @@ -1,17 +0,0 @@ -@ RUN: llvm-mc -mcpu=cortex-a8 -triple thumbv7-apple-darwin10 -filetype=obj -o - < %s | macho-dump | FileCheck %s - -_fred: - movt r3, :upper16:(_wilma-(LPC0_0+4)) -LPC0_0: - -_wilma: - .long 0 - -@ CHECK: ('_relocations', [ -@ CHECK: # Relocation 0 -@ CHECK: (('word-0', 0xb9000000), -@ CHECK: ('word-1', 0x4)), -@ CHECK: # Relocation 1 -@ CHECK: (('word-0', 0xb100fffc), -@ CHECK: ('word-1', 0x4)), - -- cgit v1.1 From df78fcd2d6ba4fd499ead3bdea2fde83dbcecab9 Mon Sep 17 00:00:00 2001 From: Chad Rosier Date: Sat, 25 Jun 2011 02:04:56 +0000 Subject: Enable tail call optimization in the presence of a byval (x86-32 and x86-64). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133858 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86ISelLowering.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 6c606be..bab15e6 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -2505,6 +2505,10 @@ bool MatchingStackOffset(SDValue Arg, unsigned Offset, ISD::ArgFlagsTy Flags, if (!FINode) return false; FI = FINode->getIndex(); + } else if (Arg.getOpcode() == ISD::FrameIndex && Flags.isByVal()) { + FrameIndexSDNode *FINode = dyn_cast(Arg); + FI = FINode->getIndex(); + Bytes = Flags.getByValSize(); } else return false; -- cgit v1.1 From fdfd40b5f1c6559da2368ee1c90cbb52d44b9c08 Mon Sep 17 00:00:00 2001 From: Oscar Fuentes Date: Sat, 25 Jun 2011 02:10:19 +0000 Subject: Update CMake library dependencies. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133859 91177308-0d34-0410-b5e6-96231b3b80d8 --- cmake/modules/LLVMLibDeps.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/modules/LLVMLibDeps.cmake b/cmake/modules/LLVMLibDeps.cmake index f9e2998..9d99937 100644 --- a/cmake/modules/LLVMLibDeps.cmake +++ b/cmake/modules/LLVMLibDeps.cmake @@ -60,6 +60,7 @@ set(MSVC_LIB_DEPS_LLVMTransformUtils LLVMAnalysis LLVMCore LLVMSupport LLVMTarge set(MSVC_LIB_DEPS_LLVMX86AsmParser LLVMMC LLVMMCParser LLVMSupport LLVMTarget LLVMX86Info) set(MSVC_LIB_DEPS_LLVMX86AsmPrinter LLVMMC LLVMSupport LLVMX86Utils) set(MSVC_LIB_DEPS_LLVMX86CodeGen LLVMAnalysis LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMSelectionDAG LLVMSupport LLVMTarget LLVMX86AsmPrinter LLVMX86Info LLVMX86Utils) +set(MSVC_LIB_DEPS_LLVMX86Desc LLVMX86Info) set(MSVC_LIB_DEPS_LLVMX86Disassembler LLVMMC LLVMSupport LLVMX86Info) set(MSVC_LIB_DEPS_LLVMX86Info LLVMMC LLVMSupport) set(MSVC_LIB_DEPS_LLVMX86Utils LLVMCore LLVMSupport) -- cgit v1.1 From 644eb9befc4334f408cb6bed90ec5ed1a30f32a6 Mon Sep 17 00:00:00 2001 From: Chad Rosier Date: Sat, 25 Jun 2011 02:44:56 +0000 Subject: Test case for r133858 (tail call optimize in the presence of byval). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133863 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/CodeGen/X86/sibcall-byval.ll | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 test/CodeGen/X86/sibcall-byval.ll diff --git a/test/CodeGen/X86/sibcall-byval.ll b/test/CodeGen/X86/sibcall-byval.ll new file mode 100644 index 0000000..c335f30 --- /dev/null +++ b/test/CodeGen/X86/sibcall-byval.ll @@ -0,0 +1,31 @@ +; RUN: llc < %s -mtriple=i386-apple-darwin | FileCheck %s -check-prefix=32 +; RUN: llc < %s -mtriple=x86_64-apple-darwin | FileCheck %s -check-prefix=64 + +%struct.p = type { i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32 } + +define i32 @f(%struct.p* byval align 4 %q) nounwind ssp { +entry: +; 32: _f: +; 32: jmp L_g$stub + +; 64: _f: +; 64: jmp _g + %call = tail call i32 @g(%struct.p* byval align 4 %q) nounwind + ret i32 %call +} + +declare i32 @g(%struct.p* byval align 4) + +define i32 @h(%struct.p* byval align 4 %q, i32 %r) nounwind ssp { +entry: +; 32: _h: +; 32: jmp L_i$stub + +; 64: _h: +; 64: jmp _i + + %call = tail call i32 @i(%struct.p* byval align 4 %q, i32 %r) nounwind + ret i32 %call +} + +declare i32 @i(%struct.p* byval align 4, i32) -- cgit v1.1 From 3e64427cb3381b6fdb498bcdbf2abef0bf22e0f0 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Sat, 25 Jun 2011 17:08:50 +0000 Subject: Enhance the sanity check for block sizes; check that the resulting pointer is pointing to the range [first character, last character] instead of just not after the last character. Patch by Yan Ivnitskiy! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133867 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Bitcode/BitstreamReader.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h index 779ef5f..0ca3ad1 100644 --- a/include/llvm/Bitcode/BitstreamReader.h +++ b/include/llvm/Bitcode/BitstreamReader.h @@ -375,10 +375,12 @@ public: // Check that the block wasn't partially defined, and that the offset isn't // bogus. - if (AtEndOfStream() || NextChar+NumWords*4 > BitStream->getLastChar()) + const unsigned char *const SkipTo = NextChar + NumWords*4; + if (AtEndOfStream() || SkipTo > BitStream->getLastChar() || + SkipTo < BitStream->getFirstChar()) return true; - NextChar += NumWords*4; + NextChar = SkipTo; return false; } -- cgit v1.1 From d2a02f409e20f64a33e5dc55926e97bd710386c8 Mon Sep 17 00:00:00 2001 From: "Michael J. Spencer" Date: Sat, 25 Jun 2011 17:42:56 +0000 Subject: Add Object/Error. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133868 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/Error.h | 49 ++++++++++++++++++++++++++++++++++++++++ lib/Object/CMakeLists.txt | 1 + lib/Object/Error.cpp | 55 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 105 insertions(+) create mode 100644 include/llvm/Object/Error.h create mode 100644 lib/Object/Error.cpp diff --git a/include/llvm/Object/Error.h b/include/llvm/Object/Error.h new file mode 100644 index 0000000..c1a4629 --- /dev/null +++ b/include/llvm/Object/Error.h @@ -0,0 +1,49 @@ +//===- Error.h - system_error extensions for Object -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This declares a new error_category for the Object library. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_ERROR_H +#define LLVM_OBJECT_ERROR_H + +#include "llvm/Support/system_error.h" + +namespace llvm { +namespace object { + +const error_category &object_category(); + +struct object_error { +enum _ { + success = 0, + invalid_file_type, + parse_failed +}; + _ v_; + + object_error(_ v) : v_(v) {} + explicit object_error(int v) : v_(_(v)) {} + operator int() const {return v_;} +}; + +inline error_code make_error_code(object_error e) { + return error_code(static_cast(e), object_category()); +} + +} // end namespace object. + +template <> struct is_error_code_enum : true_type { }; + +template <> struct is_error_code_enum : true_type { }; + +} // end namespace llvm. + +#endif diff --git a/lib/Object/CMakeLists.txt b/lib/Object/CMakeLists.txt index 703d385..e32940e 100644 --- a/lib/Object/CMakeLists.txt +++ b/lib/Object/CMakeLists.txt @@ -1,6 +1,7 @@ add_llvm_library(LLVMObject COFFObjectFile.cpp ELFObjectFile.cpp + Error.cpp MachOObject.cpp MachOObjectFile.cpp Object.cpp diff --git a/lib/Object/Error.cpp b/lib/Object/Error.cpp new file mode 100644 index 0000000..40f97d4 --- /dev/null +++ b/lib/Object/Error.cpp @@ -0,0 +1,55 @@ +//===- Error.cpp - system_error extensions for Object -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This defines a new error_category for the Object library. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Object/Error.h" +#include "llvm/Support/ErrorHandling.h" + +using namespace llvm; +using namespace object; + +namespace { +class _object_error_category : public _do_message { +public: + virtual const char* name() const; + virtual std::string message(int ev) const; + virtual error_condition default_error_condition(int ev) const; +}; +} + +const char *_object_error_category::name() const { + return "llvm.object"; +} + +std::string _object_error_category::message(int ev) const { + switch (ev) { + case object_error::success: return "Success"; + case object_error::invalid_file_type: + return "The file was not recognized as a valid object file"; + case object_error::parse_failed: + return "Invalid data was encountered while parsing the file"; + default: + llvm_unreachable("An enumerator of object_error does not have a message " + "defined."); + } +} + +error_condition _object_error_category::default_error_condition(int ev) const { + if (ev == object_error::success) + return errc::success; + return errc::invalid_argument; +} + +const error_category &object::object_category() { + static _object_error_category o; + return o; +} -- cgit v1.1 From c44c915372ee453bd63a8b6b3eca586ab6f18545 Mon Sep 17 00:00:00 2001 From: "Michael J. Spencer" Date: Sat, 25 Jun 2011 17:54:29 +0000 Subject: Add Binary class. This is a cleaner parent than ObjectFile. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133869 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/Binary.h | 64 ++++++++++++++++++++++++++++++++++++++++++++ lib/Object/Binary.cpp | 50 ++++++++++++++++++++++++++++++++++ lib/Object/CMakeLists.txt | 1 + 3 files changed, 115 insertions(+) create mode 100644 include/llvm/Object/Binary.h create mode 100644 lib/Object/Binary.cpp diff --git a/include/llvm/Object/Binary.h b/include/llvm/Object/Binary.h new file mode 100644 index 0000000..89cd24b --- /dev/null +++ b/include/llvm/Object/Binary.h @@ -0,0 +1,64 @@ +//===- Binary.h - A generic binary file -------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the Binary class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_BINARY_H +#define LLVM_OBJECT_BINARY_H + +#include "llvm/ADT/OwningPtr.h" +#include "llvm/Object/Error.h" + +namespace llvm { + +class MemoryBuffer; +class StringRef; + +namespace object { + +class Binary { +private: + Binary(); // = delete + Binary(const Binary &other); // = delete + + unsigned int TypeID; + +protected: + MemoryBuffer *Data; + + Binary(unsigned int Type, MemoryBuffer *Source); + + enum { + isArchive, + isCOFF, + isELF, + isMachO, + isObject + }; + +public: + virtual ~Binary(); + + StringRef getData() const; + StringRef getFileName() const; + + // Cast methods. + unsigned int getType() const { return TypeID; } + static inline bool classof(Binary const *v) { return true; } +}; + +error_code createBinary(MemoryBuffer *Source, OwningPtr &Result); +error_code createBinary(StringRef Path, OwningPtr &Result); + +} +} + +#endif diff --git a/lib/Object/Binary.cpp b/lib/Object/Binary.cpp new file mode 100644 index 0000000..75f5a58 --- /dev/null +++ b/lib/Object/Binary.cpp @@ -0,0 +1,50 @@ +//===- Binary.cpp - A generic binary file -----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the Binary class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Object/Binary.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Path.h" + +using namespace llvm; +using namespace object; + +Binary::~Binary() { + delete Data; +} + +Binary::Binary(unsigned int Type, MemoryBuffer *Source) + : TypeID(Type) + , Data(Source) {} + +StringRef Binary::getData() const { + return Data->getBuffer(); +} + +StringRef Binary::getFileName() const { + return Data->getBufferIdentifier(); +} + +error_code object::createBinary(MemoryBuffer *Source, + OwningPtr &Result) { + // We don't support any at the moment. + delete Source; + return object_error::invalid_file_type; +} + +error_code object::createBinary(StringRef Path, OwningPtr &Result) { + OwningPtr File; + if (error_code ec = MemoryBuffer::getFile(Path, File)) + return ec; + return createBinary(File.take(), Result); +} diff --git a/lib/Object/CMakeLists.txt b/lib/Object/CMakeLists.txt index e32940e..68e5e94 100644 --- a/lib/Object/CMakeLists.txt +++ b/lib/Object/CMakeLists.txt @@ -1,4 +1,5 @@ add_llvm_library(LLVMObject + Binary.cpp COFFObjectFile.cpp ELFObjectFile.cpp Error.cpp -- cgit v1.1 From 001c9205fca2220480589ec355cb6ec701a37e08 Mon Sep 17 00:00:00 2001 From: "Michael J. Spencer" Date: Sat, 25 Jun 2011 17:54:50 +0000 Subject: Make Binary the parent of ObjectFile and update children to new interface. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133870 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/Binary.h | 7 ++- include/llvm/Object/COFF.h | 111 +++++++++++++++++++++++++++++++++ include/llvm/Object/ObjectFile.h | 29 +++++---- lib/Object/Binary.cpp | 52 +++++++++++++++- lib/Object/COFFObjectFile.cpp | 128 +++++---------------------------------- lib/Object/ELFObjectFile.cpp | 42 +++++++------ lib/Object/MachOObjectFile.cpp | 7 ++- lib/Object/ObjectFile.cpp | 14 +---- tools/llvm-nm/llvm-nm.cpp | 2 +- 9 files changed, 222 insertions(+), 170 deletions(-) create mode 100644 include/llvm/Object/COFF.h diff --git a/include/llvm/Object/Binary.h b/include/llvm/Object/Binary.h index 89cd24b..cd092fd 100644 --- a/include/llvm/Object/Binary.h +++ b/include/llvm/Object/Binary.h @@ -38,10 +38,13 @@ protected: enum { isArchive, + + // Object and children. + isObject, isCOFF, isELF, isMachO, - isObject + lastObject }; public: @@ -52,7 +55,7 @@ public: // Cast methods. unsigned int getType() const { return TypeID; } - static inline bool classof(Binary const *v) { return true; } + static inline bool classof(const Binary *v) { return true; } }; error_code createBinary(MemoryBuffer *Source, OwningPtr &Result); diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h new file mode 100644 index 0000000..5ed8aa0 --- /dev/null +++ b/include/llvm/Object/COFF.h @@ -0,0 +1,111 @@ +//===- COFF.h - COFF object file implementation -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the COFFObjectFile class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_COFF_H +#define LLVM_OBJECT_COFF_H + +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/COFF.h" +#include "llvm/Support/Endian.h" + +namespace llvm { +namespace object { + +struct coff_file_header { + support::ulittle16_t Machine; + support::ulittle16_t NumberOfSections; + support::ulittle32_t TimeDateStamp; + support::ulittle32_t PointerToSymbolTable; + support::ulittle32_t NumberOfSymbols; + support::ulittle16_t SizeOfOptionalHeader; + support::ulittle16_t Characteristics; +}; + +struct coff_symbol { + struct StringTableOffset { + support::ulittle32_t Zeroes; + support::ulittle32_t Offset; + }; + + union { + char ShortName[8]; + StringTableOffset Offset; + } Name; + + support::ulittle32_t Value; + support::little16_t SectionNumber; + + struct { + support::ulittle8_t BaseType; + support::ulittle8_t ComplexType; + } Type; + + support::ulittle8_t StorageClass; + support::ulittle8_t NumberOfAuxSymbols; +}; + +struct coff_section { + char Name[8]; + support::ulittle32_t VirtualSize; + support::ulittle32_t VirtualAddress; + support::ulittle32_t SizeOfRawData; + support::ulittle32_t PointerToRawData; + support::ulittle32_t PointerToRelocations; + support::ulittle32_t PointerToLinenumbers; + support::ulittle16_t NumberOfRelocations; + support::ulittle16_t NumberOfLinenumbers; + support::ulittle32_t Characteristics; +}; + +class COFFObjectFile : public ObjectFile { +private: + uint64_t HeaderOff; + const coff_file_header *Header; + const coff_section *SectionTable; + const coff_symbol *SymbolTable; + const char *StringTable; + + const coff_section *getSection(std::size_t index) const; + const char *getString(std::size_t offset) const; + +protected: + virtual SymbolRef getSymbolNext(DataRefImpl Symb) const; + virtual StringRef getSymbolName(DataRefImpl Symb) const; + virtual uint64_t getSymbolAddress(DataRefImpl Symb) const; + virtual uint64_t getSymbolSize(DataRefImpl Symb) const; + virtual char getSymbolNMTypeChar(DataRefImpl Symb) const; + virtual bool isSymbolInternal(DataRefImpl Symb) const; + + virtual SectionRef getSectionNext(DataRefImpl Sec) const; + virtual StringRef getSectionName(DataRefImpl Sec) const; + virtual uint64_t getSectionAddress(DataRefImpl Sec) const; + virtual uint64_t getSectionSize(DataRefImpl Sec) const; + virtual StringRef getSectionContents(DataRefImpl Sec) const; + virtual bool isSectionText(DataRefImpl Sec) const; + +public: + COFFObjectFile(MemoryBuffer *Object, error_code &ec); + virtual symbol_iterator begin_symbols() const; + virtual symbol_iterator end_symbols() const; + virtual section_iterator begin_sections() const; + virtual section_iterator end_sections() const; + + virtual uint8_t getBytesInAddress() const; + virtual StringRef getFileFormatName() const; + virtual unsigned getArch() const; +}; + +} +} + +#endif diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h index eee9d44..d16e4dd 100644 --- a/include/llvm/Object/ObjectFile.h +++ b/include/llvm/Object/ObjectFile.h @@ -14,15 +14,13 @@ #ifndef LLVM_OBJECT_OBJECT_FILE_H #define LLVM_OBJECT_OBJECT_FILE_H +#include "llvm/Object/Binary.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/MemoryBuffer.h" #include namespace llvm { - -class MemoryBuffer; -class StringRef; - namespace object { class ObjectFile; @@ -93,16 +91,17 @@ const uint64_t UnknownAddressOrSize = ~0ULL; /// ObjectFile - This class is the base class for all object file types. /// Concrete instances of this object are created by createObjectFile, which /// figure out which type to create. -class ObjectFile { +class ObjectFile : public Binary { private: ObjectFile(); // = delete ObjectFile(const ObjectFile &other); // = delete protected: - MemoryBuffer *MapFile; - const uint8_t *base; + ObjectFile(unsigned int Type, MemoryBuffer *source, error_code &ec); - ObjectFile(MemoryBuffer *Object); + const uint8_t *base() const { + return reinterpret_cast(Data->getBufferStart()); + } // These functions are for SymbolRef to call internally. The main goal of // this is to allow SymbolRef::SymbolPimpl to point directly to the symbol @@ -156,8 +155,6 @@ public: typedef content_iterator symbol_iterator; typedef content_iterator section_iterator; - virtual ~ObjectFile(); - virtual symbol_iterator begin_symbols() const = 0; virtual symbol_iterator end_symbols() const = 0; @@ -171,8 +168,6 @@ public: virtual StringRef getFileFormatName() const = 0; virtual /* Triple::ArchType */ unsigned getArch() const = 0; - StringRef getFilename() const; - /// @returns Pointer to ObjectFile subclass to handle this type of object. /// @param ObjectPath The path to the object file. ObjectPath.isObject must /// return true. @@ -180,12 +175,16 @@ public: static ObjectFile *createObjectFile(StringRef ObjectPath); static ObjectFile *createObjectFile(MemoryBuffer *Object); -private: + static inline bool classof(const Binary *v) { + return v->getType() >= isObject && + v->getType() < lastObject; + } + static inline bool classof(const ObjectFile *v) { return true; } + +public: static ObjectFile *createCOFFObjectFile(MemoryBuffer *Object); static ObjectFile *createELFObjectFile(MemoryBuffer *Object); static ObjectFile *createMachOObjectFile(MemoryBuffer *Object); - static ObjectFile *createArchiveObjectFile(MemoryBuffer *Object); - static ObjectFile *createLibObjectFile(MemoryBuffer *Object); }; // Inline function definitions. diff --git a/lib/Object/Binary.cpp b/lib/Object/Binary.cpp index 75f5a58..4b31c75 100644 --- a/lib/Object/Binary.cpp +++ b/lib/Object/Binary.cpp @@ -16,6 +16,10 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" +// Include headers for createBinary. +#include "llvm/Object/ObjectFile.h" +#include "llvm/Object/COFF.h" + using namespace llvm; using namespace object; @@ -37,9 +41,51 @@ StringRef Binary::getFileName() const { error_code object::createBinary(MemoryBuffer *Source, OwningPtr &Result) { - // We don't support any at the moment. - delete Source; - return object_error::invalid_file_type; + OwningPtr scopedSource(Source); + if (!Source) + return make_error_code(errc::invalid_argument); + if (Source->getBufferSize() < 64) + return object_error::invalid_file_type; + sys::LLVMFileType type = sys::IdentifyFileType(Source->getBufferStart(), + static_cast(Source->getBufferSize())); + error_code ec; + switch (type) { + case sys::ELF_Relocatable_FileType: + case sys::ELF_Executable_FileType: + case sys::ELF_SharedObject_FileType: + case sys::ELF_Core_FileType: { + OwningPtr ret( + ObjectFile::createELFObjectFile(scopedSource.take())); + if (!ret) + return object_error::invalid_file_type; + Result.swap(ret); + return object_error::success; + } + case sys::Mach_O_Object_FileType: + case sys::Mach_O_Executable_FileType: + case sys::Mach_O_FixedVirtualMemorySharedLib_FileType: + case sys::Mach_O_Core_FileType: + case sys::Mach_O_PreloadExecutable_FileType: + case sys::Mach_O_DynamicallyLinkedSharedLib_FileType: + case sys::Mach_O_DynamicLinker_FileType: + case sys::Mach_O_Bundle_FileType: + case sys::Mach_O_DynamicallyLinkedSharedLibStub_FileType: { + OwningPtr ret( + ObjectFile::createMachOObjectFile(scopedSource.take())); + if (!ret) + return object_error::invalid_file_type; + Result.swap(ret); + return object_error::success; + } + case sys::COFF_FileType: { + OwningPtr ret(new COFFObjectFile(scopedSource.take(), ec)); + if (ec) return ec; + Result.swap(ret); + return object_error::success; + } + default: // Unrecognized object file format. + return object_error::invalid_file_type; + } } error_code object::createBinary(StringRef Path, OwningPtr &Result) { diff --git a/lib/Object/COFFObjectFile.cpp b/lib/Object/COFFObjectFile.cpp index 86bf44b..60fc880 100644 --- a/lib/Object/COFFObjectFile.cpp +++ b/lib/Object/COFFObjectFile.cpp @@ -11,11 +11,9 @@ // //===----------------------------------------------------------------------===// +#include "llvm/Object/COFF.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" -#include "llvm/Object/ObjectFile.h" -#include "llvm/Support/COFF.h" -#include "llvm/Support/Endian.h" using namespace llvm; using namespace object; @@ -27,107 +25,6 @@ using support::ulittle32_t; using support::little16_t; } -namespace { -struct coff_file_header { - ulittle16_t Machine; - ulittle16_t NumberOfSections; - ulittle32_t TimeDateStamp; - ulittle32_t PointerToSymbolTable; - ulittle32_t NumberOfSymbols; - ulittle16_t SizeOfOptionalHeader; - ulittle16_t Characteristics; -}; -} - -extern char coff_file_header_layout_static_assert - [sizeof(coff_file_header) == 20 ? 1 : -1]; - -namespace { -struct coff_symbol { - struct StringTableOffset { - ulittle32_t Zeroes; - ulittle32_t Offset; - }; - - union { - char ShortName[8]; - StringTableOffset Offset; - } Name; - - ulittle32_t Value; - little16_t SectionNumber; - - struct { - ulittle8_t BaseType; - ulittle8_t ComplexType; - } Type; - - ulittle8_t StorageClass; - ulittle8_t NumberOfAuxSymbols; -}; -} - -extern char coff_coff_symbol_layout_static_assert - [sizeof(coff_symbol) == 18 ? 1 : -1]; - -namespace { -struct coff_section { - char Name[8]; - ulittle32_t VirtualSize; - ulittle32_t VirtualAddress; - ulittle32_t SizeOfRawData; - ulittle32_t PointerToRawData; - ulittle32_t PointerToRelocations; - ulittle32_t PointerToLinenumbers; - ulittle16_t NumberOfRelocations; - ulittle16_t NumberOfLinenumbers; - ulittle32_t Characteristics; -}; -} - -extern char coff_coff_section_layout_static_assert - [sizeof(coff_section) == 40 ? 1 : -1]; - -namespace { -class COFFObjectFile : public ObjectFile { -private: - uint64_t HeaderOff; - const coff_file_header *Header; - const coff_section *SectionTable; - const coff_symbol *SymbolTable; - const char *StringTable; - - const coff_section *getSection(std::size_t index) const; - const char *getString(std::size_t offset) const; - -protected: - virtual SymbolRef getSymbolNext(DataRefImpl Symb) const; - virtual StringRef getSymbolName(DataRefImpl Symb) const; - virtual uint64_t getSymbolAddress(DataRefImpl Symb) const; - virtual uint64_t getSymbolSize(DataRefImpl Symb) const; - virtual char getSymbolNMTypeChar(DataRefImpl Symb) const; - virtual bool isSymbolInternal(DataRefImpl Symb) const; - - virtual SectionRef getSectionNext(DataRefImpl Sec) const; - virtual StringRef getSectionName(DataRefImpl Sec) const; - virtual uint64_t getSectionAddress(DataRefImpl Sec) const; - virtual uint64_t getSectionSize(DataRefImpl Sec) const; - virtual StringRef getSectionContents(DataRefImpl Sec) const; - virtual bool isSectionText(DataRefImpl Sec) const; - -public: - COFFObjectFile(MemoryBuffer *Object); - virtual symbol_iterator begin_symbols() const; - virtual symbol_iterator end_symbols() const; - virtual section_iterator begin_sections() const; - virtual section_iterator end_sections() const; - - virtual uint8_t getBytesInAddress() const; - virtual StringRef getFileFormatName() const; - virtual unsigned getArch() const; -}; -} // end namespace - SymbolRef COFFObjectFile::getSymbolNext(DataRefImpl Symb) const { const coff_symbol *symb = reinterpret_cast(Symb.p); symb += 1 + symb->NumberOfAuxSymbols; @@ -274,7 +171,8 @@ uint64_t COFFObjectFile::getSectionSize(DataRefImpl Sec) const { StringRef COFFObjectFile::getSectionContents(DataRefImpl Sec) const { const coff_section *sec = reinterpret_cast(Sec.p); - return StringRef(reinterpret_cast(base + sec->PointerToRawData), + return StringRef(reinterpret_cast(base() + + sec->PointerToRawData), sec->SizeOfRawData); } @@ -283,29 +181,30 @@ bool COFFObjectFile::isSectionText(DataRefImpl Sec) const { return sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE; } -COFFObjectFile::COFFObjectFile(MemoryBuffer *Object) - : ObjectFile(Object) { +COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &ec) + : ObjectFile(Binary::isCOFF, Object, ec) { HeaderOff = 0; - if (base[0] == 0x4d && base[1] == 0x5a) { + if (base()[0] == 0x4d && base()[1] == 0x5a) { // PE/COFF, seek through MS-DOS compatibility stub and 4-byte // PE signature to find 'normal' COFF header. - HeaderOff += *reinterpret_cast(base + 0x3c); + HeaderOff += *reinterpret_cast(base() + 0x3c); HeaderOff += 4; } - Header = reinterpret_cast(base + HeaderOff); + Header = reinterpret_cast(base() + HeaderOff); SectionTable = - reinterpret_cast( base + reinterpret_cast( base() + HeaderOff + sizeof(coff_file_header) + Header->SizeOfOptionalHeader); SymbolTable = - reinterpret_cast(base + Header->PointerToSymbolTable); + reinterpret_cast(base() + + Header->PointerToSymbolTable); // Find string table. - StringTable = reinterpret_cast(base) + StringTable = reinterpret_cast(base()) + Header->PointerToSymbolTable + Header->NumberOfSymbols * 18; } @@ -382,7 +281,8 @@ const char *COFFObjectFile::getString(std::size_t offset) const { namespace llvm { ObjectFile *ObjectFile::createCOFFObjectFile(MemoryBuffer *Object) { - return new COFFObjectFile(Object); + error_code ec; + return new COFFObjectFile(Object, ec); } } // end namespace llvm diff --git a/lib/Object/ELFObjectFile.cpp b/lib/Object/ELFObjectFile.cpp index d2a2726..1c4dcea 100644 --- a/lib/Object/ELFObjectFile.cpp +++ b/lib/Object/ELFObjectFile.cpp @@ -237,7 +237,7 @@ protected: virtual bool isSectionText(DataRefImpl Sec) const; public: - ELFObjectFile(MemoryBuffer *Object); + ELFObjectFile(MemoryBuffer *Object, error_code &ec); virtual symbol_iterator begin_symbols() const; virtual symbol_iterator end_symbols() const; virtual section_iterator begin_sections() const; @@ -259,9 +259,9 @@ void ELFObjectFile // an error object around. if (!( symb && SymbolTableSection - && symb >= (const Elf_Sym*)(base + && symb >= (const Elf_Sym*)(base() + SymbolTableSection->sh_offset) - && symb < (const Elf_Sym*)(base + && symb < (const Elf_Sym*)(base() + SymbolTableSection->sh_offset + SymbolTableSection->sh_size))) // FIXME: Proper error handling. @@ -444,7 +444,7 @@ template StringRef ELFObjectFile ::getSectionContents(DataRefImpl Sec) const { const Elf_Shdr *sec = reinterpret_cast(Sec.p); - const char *start = (char*)base + sec->sh_offset; + const char *start = (char*)base() + sec->sh_offset; return StringRef(start, sec->sh_size); } @@ -458,21 +458,22 @@ bool ELFObjectFile } template -ELFObjectFile::ELFObjectFile(MemoryBuffer *Object) - : ObjectFile(Object) +ELFObjectFile::ELFObjectFile(MemoryBuffer *Object + , error_code &ec) + : ObjectFile(Binary::isELF, Object, ec) , SectionHeaderTable(0) , dot_shstrtab_sec(0) , dot_strtab_sec(0) { - Header = reinterpret_cast(base); + Header = reinterpret_cast(base()); if (Header->e_shoff == 0) return; SectionHeaderTable = - reinterpret_cast(base + Header->e_shoff); + reinterpret_cast(base() + Header->e_shoff); uint32_t SectionTableSize = Header->e_shnum * Header->e_shentsize; if (!( (const uint8_t *)SectionHeaderTable + SectionTableSize - <= base + MapFile->getBufferSize())) + <= base() + Data->getBufferSize())) // FIXME: Proper error handling. report_fatal_error("Section table goes past end of file!"); @@ -491,7 +492,7 @@ ELFObjectFile::ELFObjectFile(MemoryBuffer *Object) dot_shstrtab_sec = getSection(Header->e_shstrndx); if (dot_shstrtab_sec) { // Verify that the last byte in the string table in a null. - if (((const char*)base + dot_shstrtab_sec->sh_offset) + if (((const char*)base() + dot_shstrtab_sec->sh_offset) [dot_shstrtab_sec->sh_size - 1] != 0) // FIXME: Proper error handling. report_fatal_error("String table must end with a null terminator!"); @@ -509,7 +510,7 @@ ELFObjectFile::ELFObjectFile(MemoryBuffer *Object) // FIXME: Proper error handling. report_fatal_error("Already found section named .strtab!"); dot_strtab_sec = sh; - const char *dot_strtab = (const char*)base + sh->sh_offset; + const char *dot_strtab = (const char*)base() + sh->sh_offset; if (dot_strtab[sh->sh_size - 1] != 0) // FIXME: Proper error handling. report_fatal_error("String table must end with a null terminator!"); @@ -548,7 +549,7 @@ ObjectFile::section_iterator ELFObjectFile ::begin_sections() const { DataRefImpl ret; memset(&ret, 0, sizeof(DataRefImpl)); - ret.p = reinterpret_cast(base + Header->e_shoff); + ret.p = reinterpret_cast(base() + Header->e_shoff); return section_iterator(SectionRef(ret, this)); } @@ -557,7 +558,7 @@ ObjectFile::section_iterator ELFObjectFile ::end_sections() const { DataRefImpl ret; memset(&ret, 0, sizeof(DataRefImpl)); - ret.p = reinterpret_cast(base + ret.p = reinterpret_cast(base() + Header->e_shoff + (Header->e_shentsize * Header->e_shnum)); return section_iterator(SectionRef(ret, this)); @@ -613,7 +614,7 @@ const typename ELFObjectFile::Elf_Sym * ELFObjectFile::getSymbol(DataRefImpl Symb) const { const Elf_Shdr *sec = SymbolTableSections[Symb.d.b]; return reinterpret_cast( - base + base() + sec->sh_offset + (Symb.d.a * sec->sh_entsize)); } @@ -656,8 +657,8 @@ const char *ELFObjectFile assert(section && section->sh_type == ELF::SHT_STRTAB && "Invalid section!"); if (offset >= section->sh_size) // FIXME: Proper error handling. - report_fatal_error("Sybol name offset outside of string table!"); - return (const char *)base + section->sh_offset + offset; + report_fatal_error("Symbol name offset outside of string table!"); + return (const char *)base() + section->sh_offset + offset; } // EI_CLASS, EI_DATA. @@ -673,14 +674,15 @@ namespace llvm { ObjectFile *ObjectFile::createELFObjectFile(MemoryBuffer *Object) { std::pair Ident = getElfArchType(Object); + error_code ec; if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2LSB) - return new ELFObjectFile(Object); + return new ELFObjectFile(Object, ec); else if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2MSB) - return new ELFObjectFile(Object); + return new ELFObjectFile(Object, ec); else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2LSB) - return new ELFObjectFile(Object); + return new ELFObjectFile(Object, ec); else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2MSB) - return new ELFObjectFile(Object); + return new ELFObjectFile(Object, ec); // FIXME: Proper error handling. report_fatal_error("Not an ELF object file!"); } diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 877cbfb..3b76c6f 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -32,8 +32,8 @@ typedef MachOObject::LoadCommandInfo LoadCommandInfo; class MachOObjectFile : public ObjectFile { public: - MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO) - : ObjectFile(Object), + MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO, error_code &ec) + : ObjectFile(Binary::isMachO, Object, ec), MachOObj(MOO), RegisteredStringTable(std::numeric_limits::max()) {} @@ -73,11 +73,12 @@ private: }; ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { + error_code ec; std::string Err; MachOObject *MachOObj = MachOObject::LoadFromBuffer(Buffer, &Err); if (!MachOObj) return NULL; - return new MachOObjectFile(Buffer, MachOObj); + return new MachOObjectFile(Buffer, MachOObj, ec); } /*===-- Symbols -----------------------------------------------------------===*/ diff --git a/lib/Object/ObjectFile.cpp b/lib/Object/ObjectFile.cpp index 47b6311..a7798df 100644 --- a/lib/Object/ObjectFile.cpp +++ b/lib/Object/ObjectFile.cpp @@ -21,18 +21,8 @@ using namespace llvm; using namespace object; -ObjectFile::ObjectFile(MemoryBuffer *Object) - : MapFile(Object) { - assert(MapFile && "Must be a valid MemoryBuffer!"); - base = reinterpret_cast(MapFile->getBufferStart()); -} - -ObjectFile::~ObjectFile() { - delete MapFile; -} - -StringRef ObjectFile::getFilename() const { - return MapFile->getBufferIdentifier(); +ObjectFile::ObjectFile(unsigned int Type, MemoryBuffer *source, error_code &ec) + : Binary(Type, source) { } ObjectFile *ObjectFile::createObjectFile(MemoryBuffer *Object) { diff --git a/tools/llvm-nm/llvm-nm.cpp b/tools/llvm-nm/llvm-nm.cpp index 1afa503..5315b6c 100644 --- a/tools/llvm-nm/llvm-nm.cpp +++ b/tools/llvm-nm/llvm-nm.cpp @@ -277,7 +277,7 @@ static void DumpSymbolNamesFromObject(ObjectFile *obj) { SymbolList.push_back(s); } - CurrentFilename = obj->getFilename(); + CurrentFilename = obj->getFileName(); SortAndPrintSymbolList(); } -- cgit v1.1 From 76fb9b0e5f553f03321777ff634eb245dd8a821e Mon Sep 17 00:00:00 2001 From: "Michael J. Spencer" Date: Sat, 25 Jun 2011 17:54:59 +0000 Subject: Modify llvm-nm to use new Binary creation method. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133871 91177308-0d34-0410-b5e6-96231b3b80d8 --- tools/llvm-nm/llvm-nm.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/llvm-nm/llvm-nm.cpp b/tools/llvm-nm/llvm-nm.cpp index 5315b6c..f6eb33c 100644 --- a/tools/llvm-nm/llvm-nm.cpp +++ b/tools/llvm-nm/llvm-nm.cpp @@ -317,13 +317,13 @@ static void DumpSymbolNamesFromFile(std::string &Filename) { MultipleFiles = true; std::for_each (Modules.begin(), Modules.end(), DumpSymbolNamesFromModule); } else if (aPath.isObjectFile()) { - std::auto_ptr obj(ObjectFile::createObjectFile(aPath.str())); - if (!obj.get()) { - errs() << ToolName << ": " << Filename << ": " - << "Failed to open object file\n"; + OwningPtr obj; + if (error_code ec = object::createBinary(aPath.str(), obj)) { + errs() << ToolName << ": " << Filename << ": " << ec.message() << ".\n"; return; } - DumpSymbolNamesFromObject(obj.get()); + if (object::ObjectFile *o = dyn_cast(obj.get())) + DumpSymbolNamesFromObject(o); } else { errs() << ToolName << ": " << Filename << ": " << "unrecognizable file type\n"; -- cgit v1.1 From 25b15777df42d5d608810f6881b6c98107481d69 Mon Sep 17 00:00:00 2001 From: "Michael J. Spencer" Date: Sat, 25 Jun 2011 17:55:23 +0000 Subject: Object: Add proper error handling. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133872 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/COFF.h | 36 ++-- include/llvm/Object/Error.h | 3 +- include/llvm/Object/ObjectFile.h | 125 ++++++++------ lib/Object/COFFObjectFile.cpp | 326 +++++++++++++++++++++++++++--------- lib/Object/ELFObjectFile.cpp | 162 +++++++++++------- lib/Object/Error.cpp | 2 + lib/Object/MachOObjectFile.cpp | 106 +++++++----- lib/Object/Object.cpp | 21 ++- tools/llvm-nm/llvm-nm.cpp | 28 +++- tools/llvm-objdump/llvm-objdump.cpp | 29 +++- 10 files changed, 565 insertions(+), 273 deletions(-) diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h index 5ed8aa0..6a5e0d9 100644 --- a/include/llvm/Object/COFF.h +++ b/include/llvm/Object/COFF.h @@ -69,29 +69,33 @@ struct coff_section { class COFFObjectFile : public ObjectFile { private: - uint64_t HeaderOff; const coff_file_header *Header; const coff_section *SectionTable; const coff_symbol *SymbolTable; const char *StringTable; + uint32_t StringTableSize; - const coff_section *getSection(std::size_t index) const; - const char *getString(std::size_t offset) const; + error_code getSection(int32_t index, + const coff_section *&Res) const; + error_code getString(uint32_t offset, StringRef &Res) const; + + const coff_symbol *toSymb(DataRefImpl Symb) const; + const coff_section *toSec(DataRefImpl Sec) const; protected: - virtual SymbolRef getSymbolNext(DataRefImpl Symb) const; - virtual StringRef getSymbolName(DataRefImpl Symb) const; - virtual uint64_t getSymbolAddress(DataRefImpl Symb) const; - virtual uint64_t getSymbolSize(DataRefImpl Symb) const; - virtual char getSymbolNMTypeChar(DataRefImpl Symb) const; - virtual bool isSymbolInternal(DataRefImpl Symb) const; - - virtual SectionRef getSectionNext(DataRefImpl Sec) const; - virtual StringRef getSectionName(DataRefImpl Sec) const; - virtual uint64_t getSectionAddress(DataRefImpl Sec) const; - virtual uint64_t getSectionSize(DataRefImpl Sec) const; - virtual StringRef getSectionContents(DataRefImpl Sec) const; - virtual bool isSectionText(DataRefImpl Sec) const; + virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; + virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; + virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; + virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; + virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const; + virtual error_code isSymbolInternal(DataRefImpl Symb, bool &Res) const; + + virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const; + virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const; + virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const; + virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const; + virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const; + virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const; public: COFFObjectFile(MemoryBuffer *Object, error_code &ec); diff --git a/include/llvm/Object/Error.h b/include/llvm/Object/Error.h index c1a4629..fbaf71c 100644 --- a/include/llvm/Object/Error.h +++ b/include/llvm/Object/Error.h @@ -25,7 +25,8 @@ struct object_error { enum _ { success = 0, invalid_file_type, - parse_failed + parse_failed, + unexpected_eof }; _ v_; diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h index d16e4dd..f083d3c 100644 --- a/include/llvm/Object/ObjectFile.h +++ b/include/llvm/Object/ObjectFile.h @@ -17,6 +17,7 @@ #include "llvm/Object/Binary.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MemoryBuffer.h" #include @@ -29,7 +30,7 @@ union DataRefImpl { struct { uint32_t a, b; } d; - intptr_t p; + uintptr_t p; }; static bool operator ==(const DataRefImpl &a, const DataRefImpl &b) { @@ -38,6 +39,19 @@ static bool operator ==(const DataRefImpl &a, const DataRefImpl &b) { return std::memcmp(&a, &b, sizeof(DataRefImpl)) == 0; } +class RelocationRef { + DataRefImpl RelocationPimpl; + const ObjectFile *OwningObject; + +public: + RelocationRef() : OwningObject(NULL) { std::memset(&RelocationPimpl, 0, sizeof(RelocationPimpl)); } + RelocationRef(DataRefImpl RelocationP, const ObjectFile *Owner); + + bool operator==(const RelocationRef &Other) const; + + error_code getNext(RelocationRef &Result); +}; + /// SymbolRef - This is a value type class that represents a single symbol in /// the list of symbols in the object file. class SymbolRef { @@ -45,23 +59,24 @@ class SymbolRef { const ObjectFile *OwningObject; public: + SymbolRef() : OwningObject(NULL) { std::memset(&SymbolPimpl, 0, sizeof(SymbolPimpl)); } SymbolRef(DataRefImpl SymbolP, const ObjectFile *Owner); bool operator==(const SymbolRef &Other) const; - SymbolRef getNext() const; + error_code getNext(SymbolRef &Result) const; - StringRef getName() const; - uint64_t getAddress() const; - uint64_t getSize() const; + error_code getName(StringRef &Result) const; + error_code getAddress(uint64_t &Result) const; + error_code getSize(uint64_t &Result) const; /// Returns the ascii char that should be displayed in a symbol table dump via /// nm for this symbol. - char getNMTypeChar() const; + error_code getNMTypeChar(char &Result) const; /// Returns true for symbols that are internal to the object file format such /// as section symbols. - bool isInternal() const; + error_code isInternal(bool &Result) const; }; /// SectionRef - This is a value type class that represents a single section in @@ -71,19 +86,20 @@ class SectionRef { const ObjectFile *OwningObject; public: + SectionRef() : OwningObject(NULL) { std::memset(&SectionPimpl, 0, sizeof(SectionPimpl)); } SectionRef(DataRefImpl SectionP, const ObjectFile *Owner); bool operator==(const SectionRef &Other) const; - SectionRef getNext() const; + error_code getNext(SectionRef &Result) const; - StringRef getName() const; - uint64_t getAddress() const; - uint64_t getSize() const; - StringRef getContents() const; + error_code getName(StringRef &Result) const; + error_code getAddress(uint64_t &Result) const; + error_code getSize(uint64_t &Result) const; + error_code getContents(StringRef &Result) const; // FIXME: Move to the normalization layer when it's created. - bool isText() const; + error_code isText(bool &Result) const; }; const uint64_t UnknownAddressOrSize = ~0ULL; @@ -108,22 +124,25 @@ protected: // entry in the memory mapped object file. SymbolPimpl cannot contain any // virtual functions because then it could not point into the memory mapped // file. + // + // Implementations assume that the DataRefImpl is valid and has not been + // modified externally. It's UB otherwise. friend class SymbolRef; - virtual SymbolRef getSymbolNext(DataRefImpl Symb) const = 0; - virtual StringRef getSymbolName(DataRefImpl Symb) const = 0; - virtual uint64_t getSymbolAddress(DataRefImpl Symb) const = 0; - virtual uint64_t getSymbolSize(DataRefImpl Symb) const = 0; - virtual char getSymbolNMTypeChar(DataRefImpl Symb) const = 0; - virtual bool isSymbolInternal(DataRefImpl Symb) const = 0; + virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const = 0; + virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const = 0; + virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const =0; + virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const = 0; + virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const = 0; + virtual error_code isSymbolInternal(DataRefImpl Symb, bool &Res) const = 0; // Same as above for SectionRef. friend class SectionRef; - virtual SectionRef getSectionNext(DataRefImpl Sec) const = 0; - virtual StringRef getSectionName(DataRefImpl Sec) const = 0; - virtual uint64_t getSectionAddress(DataRefImpl Sec) const = 0; - virtual uint64_t getSectionSize(DataRefImpl Sec) const = 0; - virtual StringRef getSectionContents(DataRefImpl Sec) const = 0; - virtual bool isSectionText(DataRefImpl Sec) const = 0; + virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const = 0; + virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const = 0; + virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const =0; + virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const = 0; + virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res)const=0; + virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const = 0; public: @@ -146,8 +165,12 @@ public: return !(*this == other); } - content_iterator& operator++() { // Preincrement - Current = Current.getNext(); + content_iterator& increment(error_code &err) { + content_type next; + if (error_code ec = Current.getNext(next)) + err = ec; + else + Current = next; return *this; } }; @@ -196,28 +219,28 @@ inline bool SymbolRef::operator==(const SymbolRef &Other) const { return SymbolPimpl == Other.SymbolPimpl; } -inline SymbolRef SymbolRef::getNext() const { - return OwningObject->getSymbolNext(SymbolPimpl); +inline error_code SymbolRef::getNext(SymbolRef &Result) const { + return OwningObject->getSymbolNext(SymbolPimpl, Result); } -inline StringRef SymbolRef::getName() const { - return OwningObject->getSymbolName(SymbolPimpl); +inline error_code SymbolRef::getName(StringRef &Result) const { + return OwningObject->getSymbolName(SymbolPimpl, Result); } -inline uint64_t SymbolRef::getAddress() const { - return OwningObject->getSymbolAddress(SymbolPimpl); +inline error_code SymbolRef::getAddress(uint64_t &Result) const { + return OwningObject->getSymbolAddress(SymbolPimpl, Result); } -inline uint64_t SymbolRef::getSize() const { - return OwningObject->getSymbolSize(SymbolPimpl); +inline error_code SymbolRef::getSize(uint64_t &Result) const { + return OwningObject->getSymbolSize(SymbolPimpl, Result); } -inline char SymbolRef::getNMTypeChar() const { - return OwningObject->getSymbolNMTypeChar(SymbolPimpl); +inline error_code SymbolRef::getNMTypeChar(char &Result) const { + return OwningObject->getSymbolNMTypeChar(SymbolPimpl, Result); } -inline bool SymbolRef::isInternal() const { - return OwningObject->isSymbolInternal(SymbolPimpl); +inline error_code SymbolRef::isInternal(bool &Result) const { + return OwningObject->isSymbolInternal(SymbolPimpl, Result); } @@ -231,28 +254,28 @@ inline bool SectionRef::operator==(const SectionRef &Other) const { return SectionPimpl == Other.SectionPimpl; } -inline SectionRef SectionRef::getNext() const { - return OwningObject->getSectionNext(SectionPimpl); +inline error_code SectionRef::getNext(SectionRef &Result) const { + return OwningObject->getSectionNext(SectionPimpl, Result); } -inline StringRef SectionRef::getName() const { - return OwningObject->getSectionName(SectionPimpl); +inline error_code SectionRef::getName(StringRef &Result) const { + return OwningObject->getSectionName(SectionPimpl, Result); } -inline uint64_t SectionRef::getAddress() const { - return OwningObject->getSectionAddress(SectionPimpl); +inline error_code SectionRef::getAddress(uint64_t &Result) const { + return OwningObject->getSectionAddress(SectionPimpl, Result); } -inline uint64_t SectionRef::getSize() const { - return OwningObject->getSectionSize(SectionPimpl); +inline error_code SectionRef::getSize(uint64_t &Result) const { + return OwningObject->getSectionSize(SectionPimpl, Result); } -inline StringRef SectionRef::getContents() const { - return OwningObject->getSectionContents(SectionPimpl); +inline error_code SectionRef::getContents(StringRef &Result) const { + return OwningObject->getSectionContents(SectionPimpl, Result); } -inline bool SectionRef::isText() const { - return OwningObject->isSectionText(SectionPimpl); +inline error_code SectionRef::isText(bool &Result) const { + return OwningObject->isSectionText(SectionPimpl, Result); } } // end namespace object diff --git a/lib/Object/COFFObjectFile.cpp b/lib/Object/COFFObjectFile.cpp index 60fc880..18aad9a 100644 --- a/lib/Object/COFFObjectFile.cpp +++ b/lib/Object/COFFObjectFile.cpp @@ -25,74 +25,165 @@ using support::ulittle32_t; using support::little16_t; } -SymbolRef COFFObjectFile::getSymbolNext(DataRefImpl Symb) const { - const coff_symbol *symb = reinterpret_cast(Symb.p); +namespace { +// Returns false if size is greater than the buffer size. And sets ec. +bool checkSize(const MemoryBuffer *m, error_code &ec, uint64_t size) { + if (m->getBufferSize() < size) { + ec = object_error::unexpected_eof; + return false; + } + return true; +} + +// Returns false if any bytes in [addr, addr + size) fall outsize of m. +bool checkAddr(const MemoryBuffer *m, + error_code &ec, + uintptr_t addr, + uint64_t size) { + if (addr + size < addr || + addr + size < size || + addr + size > uintptr_t(m->getBufferEnd())) { + ec = object_error::unexpected_eof; + return false; + } + return true; +} +} + +const coff_symbol *COFFObjectFile::toSymb(DataRefImpl Symb) const { + const coff_symbol *addr = reinterpret_cast(Symb.p); + +# ifndef NDEBUG + // Verify that the symbol points to a valid entry in the symbol table. + uintptr_t offset = uintptr_t(addr) - uintptr_t(base()); + if (offset < Header->PointerToSymbolTable + || offset >= Header->PointerToSymbolTable + + (Header->NumberOfSymbols * sizeof(coff_symbol))) + report_fatal_error("Symbol was outside of symbol table."); + + assert((offset - Header->PointerToSymbolTable) % sizeof(coff_symbol) + == 0 && "Symbol did not point to the beginning of a symbol"); +# endif + + return addr; +} + +const coff_section *COFFObjectFile::toSec(DataRefImpl Sec) const { + const coff_section *addr = reinterpret_cast(Sec.p); + +# ifndef NDEBUG + // Verify that the section points to a valid entry in the section table. + if (addr < SectionTable + || addr >= (SectionTable + Header->NumberOfSections)) + report_fatal_error("Section was outside of section table."); + + uintptr_t offset = uintptr_t(addr) - uintptr_t(SectionTable); + assert(offset % sizeof(coff_section) == 0 && + "Section did not point to the beginning of a section"); +# endif + + return addr; +} + +error_code COFFObjectFile::getSymbolNext(DataRefImpl Symb, + SymbolRef &Result) const { + const coff_symbol *symb = toSymb(Symb); symb += 1 + symb->NumberOfAuxSymbols; - Symb.p = reinterpret_cast(symb); - return SymbolRef(Symb, this); + Symb.p = reinterpret_cast(symb); + Result = SymbolRef(Symb, this); + return object_error::success; } -StringRef COFFObjectFile::getSymbolName(DataRefImpl Symb) const { - const coff_symbol *symb = reinterpret_cast(Symb.p); + error_code COFFObjectFile::getSymbolName(DataRefImpl Symb, + StringRef &Result) const { + const coff_symbol *symb = toSymb(Symb); // Check for string table entry. First 4 bytes are 0. if (symb->Name.Offset.Zeroes == 0) { uint32_t Offset = symb->Name.Offset.Offset; - return StringRef(getString(Offset)); + if (error_code ec = getString(Offset, Result)) + return ec; + return object_error::success; } if (symb->Name.ShortName[7] == 0) // Null terminated, let ::strlen figure out the length. - return StringRef(symb->Name.ShortName); - // Not null terminated, use all 8 bytes. - return StringRef(symb->Name.ShortName, 8); + Result = StringRef(symb->Name.ShortName); + else + // Not null terminated, use all 8 bytes. + Result = StringRef(symb->Name.ShortName, 8); + return object_error::success; } -uint64_t COFFObjectFile::getSymbolAddress(DataRefImpl Symb) const { - const coff_symbol *symb = reinterpret_cast(Symb.p); - const coff_section *Section = getSection(symb->SectionNumber); - char Type = getSymbolNMTypeChar(Symb); +error_code COFFObjectFile::getSymbolAddress(DataRefImpl Symb, + uint64_t &Result) const { + const coff_symbol *symb = toSymb(Symb); + const coff_section *Section; + if (error_code ec = getSection(symb->SectionNumber, Section)) + return ec; + char Type; + if (error_code ec = getSymbolNMTypeChar(Symb, Type)) + return ec; if (Type == 'U' || Type == 'w') - return UnknownAddressOrSize; - if (Section) - return Section->VirtualAddress + symb->Value; - return symb->Value; + Result = UnknownAddressOrSize; + else if (Section) + Result = Section->VirtualAddress + symb->Value; + else + Result = symb->Value; + return object_error::success; } -uint64_t COFFObjectFile::getSymbolSize(DataRefImpl Symb) const { +error_code COFFObjectFile::getSymbolSize(DataRefImpl Symb, + uint64_t &Result) const { // FIXME: Return the correct size. This requires looking at all the symbols // in the same section as this symbol, and looking for either the next // symbol, or the end of the section. - const coff_symbol *symb = reinterpret_cast(Symb.p); - const coff_section *Section = getSection(symb->SectionNumber); - char Type = getSymbolNMTypeChar(Symb); + const coff_symbol *symb = toSymb(Symb); + const coff_section *Section; + if (error_code ec = getSection(symb->SectionNumber, Section)) + return ec; + char Type; + if (error_code ec = getSymbolNMTypeChar(Symb, Type)) + return ec; if (Type == 'U' || Type == 'w') - return UnknownAddressOrSize; - if (Section) - return Section->SizeOfRawData - symb->Value; - return 0; + Result = UnknownAddressOrSize; + else if (Section) + Result = Section->SizeOfRawData - symb->Value; + else + Result = 0; + return object_error::success; } -char COFFObjectFile::getSymbolNMTypeChar(DataRefImpl Symb) const { - const coff_symbol *symb = reinterpret_cast(Symb.p); - char ret = StringSwitch(getSymbolName(Symb)) +error_code COFFObjectFile::getSymbolNMTypeChar(DataRefImpl Symb, + char &Result) const { + const coff_symbol *symb = toSymb(Symb); + StringRef name; + if (error_code ec = getSymbolName(Symb, name)) + return ec; + char ret = StringSwitch(name) .StartsWith(".debug", 'N') .StartsWith(".sxdata", 'N') .Default('?'); - if (ret != '?') - return ret; + if (ret != '?') { + Result = ret; + return object_error::success; + } uint32_t Characteristics = 0; - if (const coff_section *Section = getSection(symb->SectionNumber)) { + if (symb->SectionNumber > 0) { + const coff_section *Section; + if (error_code ec = getSection(symb->SectionNumber, Section)) + return ec; Characteristics = Section->Characteristics; } switch (symb->SectionNumber) { case COFF::IMAGE_SYM_UNDEFINED: // Check storage classes. - if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL) - return 'w'; // Don't do ::toupper. - else + if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL) { + Result = 'w'; + return object_error::success; // Don't do ::toupper. + } else ret = 'u'; break; case COFF::IMAGE_SYM_ABSOLUTE: @@ -124,22 +215,28 @@ char COFFObjectFile::getSymbolNMTypeChar(DataRefImpl Symb) const { if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL) ret = ::toupper(ret); - return ret; + Result = ret; + return object_error::success; } -bool COFFObjectFile::isSymbolInternal(DataRefImpl Symb) const { - return false; +error_code COFFObjectFile::isSymbolInternal(DataRefImpl Symb, + bool &Result) const { + Result = false; + return object_error::success; } -SectionRef COFFObjectFile::getSectionNext(DataRefImpl Sec) const { - const coff_section *sec = reinterpret_cast(Sec.p); +error_code COFFObjectFile::getSectionNext(DataRefImpl Sec, + SectionRef &Result) const { + const coff_section *sec = toSec(Sec); sec += 1; - Sec.p = reinterpret_cast(sec); - return SectionRef(Sec, this); + Sec.p = reinterpret_cast(sec); + Result = SectionRef(Sec, this); + return object_error::success; } -StringRef COFFObjectFile::getSectionName(DataRefImpl Sec) const { - const coff_section *sec = reinterpret_cast(Sec.p); +error_code COFFObjectFile::getSectionName(DataRefImpl Sec, + StringRef &Result) const { + const coff_section *sec = toSec(Sec); StringRef name; if (sec->Name[7] == 0) // Null terminated, let ::strlen figure out the length. @@ -152,66 +249,117 @@ StringRef COFFObjectFile::getSectionName(DataRefImpl Sec) const { if (name[0] == '/') { uint32_t Offset; name.substr(1).getAsInteger(10, Offset); - return StringRef(getString(Offset)); + if (error_code ec = getString(Offset, name)) + return ec; } - // It's just a normal name. - return name; + Result = name; + return object_error::success; } -uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Sec) const { - const coff_section *sec = reinterpret_cast(Sec.p); - return sec->VirtualAddress; +error_code COFFObjectFile::getSectionAddress(DataRefImpl Sec, + uint64_t &Result) const { + const coff_section *sec = toSec(Sec); + Result = sec->VirtualAddress; + return object_error::success; } -uint64_t COFFObjectFile::getSectionSize(DataRefImpl Sec) const { - const coff_section *sec = reinterpret_cast(Sec.p); - return sec->SizeOfRawData; +error_code COFFObjectFile::getSectionSize(DataRefImpl Sec, + uint64_t &Result) const { + const coff_section *sec = toSec(Sec); + Result = sec->SizeOfRawData; + return object_error::success; } -StringRef COFFObjectFile::getSectionContents(DataRefImpl Sec) const { - const coff_section *sec = reinterpret_cast(Sec.p); - return StringRef(reinterpret_cast(base() - + sec->PointerToRawData), - sec->SizeOfRawData); +error_code COFFObjectFile::getSectionContents(DataRefImpl Sec, + StringRef &Result) const { + const coff_section *sec = toSec(Sec); + // The only thing that we need to verify is that the contents is contained + // within the file bounds. We don't need to make sure it doesn't cover other + // data, as there's nothing that says that is not allowed. + uintptr_t con_start = uintptr_t(base()) + sec->PointerToRawData; + uintptr_t con_end = con_start + sec->SizeOfRawData; + if (con_end >= uintptr_t(Data->getBufferEnd())) + return object_error::parse_failed; + Result = StringRef(reinterpret_cast(con_start), + sec->SizeOfRawData); + return object_error::success; } -bool COFFObjectFile::isSectionText(DataRefImpl Sec) const { - const coff_section *sec = reinterpret_cast(Sec.p); - return sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE; +error_code COFFObjectFile::isSectionText(DataRefImpl Sec, + bool &Result) const { + const coff_section *sec = toSec(Sec); + Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE; + return object_error::success; } COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &ec) : ObjectFile(Binary::isCOFF, Object, ec) { + // Check that we at least have enough room for a header. + if (!checkSize(Data, ec, sizeof(coff_file_header))) return; - HeaderOff = 0; + // The actual starting location of the COFF header in the file. This can be + // non-zero in PE/COFF files. + uint64_t HeaderStart = 0; + // Check if this is a PE/COFF file. if (base()[0] == 0x4d && base()[1] == 0x5a) { // PE/COFF, seek through MS-DOS compatibility stub and 4-byte // PE signature to find 'normal' COFF header. - HeaderOff += *reinterpret_cast(base() + 0x3c); - HeaderOff += 4; + if (!checkSize(Data, ec, 0x3c + 8)) return; + HeaderStart += *reinterpret_cast(base() + 0x3c); + // Check the PE header. ("PE\0\0") + if (StringRef(reinterpret_cast(base() + HeaderStart), 4) + != "PE\0\0") { + ec = object_error::parse_failed; + return; + } + HeaderStart += 4; // Skip the PE Header. } - Header = reinterpret_cast(base() + HeaderOff); + Header = reinterpret_cast(base() + HeaderStart); + if (!checkAddr(Data, ec, uintptr_t(Header), sizeof(coff_file_header))) + return; + SectionTable = reinterpret_cast( base() - + HeaderOff + + HeaderStart + sizeof(coff_file_header) + Header->SizeOfOptionalHeader); + if (!checkAddr(Data, ec, uintptr_t(SectionTable), + Header->NumberOfSections * sizeof(coff_section))) + return; + SymbolTable = reinterpret_cast(base() - + Header->PointerToSymbolTable); + + Header->PointerToSymbolTable); + if (!checkAddr(Data, ec, uintptr_t(SymbolTable), + Header->NumberOfSymbols * sizeof(coff_symbol))) + return; // Find string table. StringTable = reinterpret_cast(base()) - + Header->PointerToSymbolTable - + Header->NumberOfSymbols * 18; + + Header->PointerToSymbolTable + + Header->NumberOfSymbols * sizeof(coff_symbol); + if (!checkAddr(Data, ec, uintptr_t(StringTable), sizeof(ulittle32_t))) + return; + + StringTableSize = *reinterpret_cast(StringTable); + if (!checkAddr(Data, ec, uintptr_t(StringTable), StringTableSize)) + return; + // Check that the string table is null terminated if has any in it. + if (StringTableSize < 4 + || (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)) { + ec = object_error::parse_failed; + return; + } + + ec = object_error::success; } ObjectFile::symbol_iterator COFFObjectFile::begin_symbols() const { DataRefImpl ret; - memset(&ret, 0, sizeof(DataRefImpl)); + std::memset(&ret, 0, sizeof(DataRefImpl)); ret.p = reinterpret_cast(SymbolTable); return symbol_iterator(SymbolRef(ret, this)); } @@ -219,21 +367,21 @@ ObjectFile::symbol_iterator COFFObjectFile::begin_symbols() const { ObjectFile::symbol_iterator COFFObjectFile::end_symbols() const { // The symbol table ends where the string table begins. DataRefImpl ret; - memset(&ret, 0, sizeof(DataRefImpl)); + std::memset(&ret, 0, sizeof(DataRefImpl)); ret.p = reinterpret_cast(StringTable); return symbol_iterator(SymbolRef(ret, this)); } ObjectFile::section_iterator COFFObjectFile::begin_sections() const { DataRefImpl ret; - memset(&ret, 0, sizeof(DataRefImpl)); + std::memset(&ret, 0, sizeof(DataRefImpl)); ret.p = reinterpret_cast(SectionTable); return section_iterator(SectionRef(ret, this)); } ObjectFile::section_iterator COFFObjectFile::end_sections() const { DataRefImpl ret; - memset(&ret, 0, sizeof(DataRefImpl)); + std::memset(&ret, 0, sizeof(DataRefImpl)); ret.p = reinterpret_cast(SectionTable + Header->NumberOfSections); return section_iterator(SectionRef(ret, this)); } @@ -264,18 +412,30 @@ unsigned COFFObjectFile::getArch() const { } } -const coff_section *COFFObjectFile::getSection(std::size_t index) const { - if (index > 0 && index <= Header->NumberOfSections) - return SectionTable + (index - 1); - return 0; +error_code COFFObjectFile::getSection(int32_t index, + const coff_section *&Result) const { + // Check for special index values. + if (index == COFF::IMAGE_SYM_UNDEFINED || + index == COFF::IMAGE_SYM_ABSOLUTE || + index == COFF::IMAGE_SYM_DEBUG) + Result = NULL; + else if (index > 0 && index <= Header->NumberOfSections) + // We already verified the section table data, so no need to check again. + Result = SectionTable + (index - 1); + else + return object_error::parse_failed; + return object_error::success; } -const char *COFFObjectFile::getString(std::size_t offset) const { - const ulittle32_t *StringTableSize = - reinterpret_cast(StringTable); - if (offset < *StringTableSize) - return StringTable + offset; - return 0; +error_code COFFObjectFile::getString(uint32_t offset, + StringRef &Result) const { + if (StringTableSize <= 4) + // Tried to get a string from an empty string table. + return object_error::parse_failed; + if (offset >= StringTableSize) + return object_error::unexpected_eof; + Result = StringRef(StringTable + offset); + return object_error::success; } namespace llvm { diff --git a/lib/Object/ELFObjectFile.cpp b/lib/Object/ELFObjectFile.cpp index 1c4dcea..edf9824 100644 --- a/lib/Object/ELFObjectFile.cpp +++ b/lib/Object/ELFObjectFile.cpp @@ -222,19 +222,19 @@ class ELFObjectFile : public ObjectFile { const char *getString(const Elf_Shdr *section, uint32_t offset) const; protected: - virtual SymbolRef getSymbolNext(DataRefImpl Symb) const; - virtual StringRef getSymbolName(DataRefImpl Symb) const; - virtual uint64_t getSymbolAddress(DataRefImpl Symb) const; - virtual uint64_t getSymbolSize(DataRefImpl Symb) const; - virtual char getSymbolNMTypeChar(DataRefImpl Symb) const; - virtual bool isSymbolInternal(DataRefImpl Symb) const; - - virtual SectionRef getSectionNext(DataRefImpl Sec) const; - virtual StringRef getSectionName(DataRefImpl Sec) const; - virtual uint64_t getSectionAddress(DataRefImpl Sec) const; - virtual uint64_t getSectionSize(DataRefImpl Sec) const; - virtual StringRef getSectionContents(DataRefImpl Sec) const; - virtual bool isSectionText(DataRefImpl Sec) const; + virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; + virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; + virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; + virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; + virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const; + virtual error_code isSymbolInternal(DataRefImpl Symb, bool &Res) const; + + virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const; + virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const; + virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const; + virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const; + virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const; + virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const; public: ELFObjectFile(MemoryBuffer *Object, error_code &ec); @@ -269,8 +269,9 @@ void ELFObjectFile } template -SymbolRef ELFObjectFile - ::getSymbolNext(DataRefImpl Symb) const { +error_code ELFObjectFile + ::getSymbolNext(DataRefImpl Symb, + SymbolRef &Result) const { validateSymbol(Symb); const Elf_Shdr *SymbolTableSection = SymbolTableSections[Symb.d.b]; @@ -287,63 +288,80 @@ SymbolRef ELFObjectFile } } - return SymbolRef(Symb, this); + Result = SymbolRef(Symb, this); + return object_error::success; } template -StringRef ELFObjectFile - ::getSymbolName(DataRefImpl Symb) const { +error_code ELFObjectFile + ::getSymbolName(DataRefImpl Symb, + StringRef &Result) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); if (symb->st_name == 0) { const Elf_Shdr *section = getSection(symb->st_shndx); if (!section) - return ""; - return getString(dot_shstrtab_sec, section->sh_name); + Result = ""; + else + Result = getString(dot_shstrtab_sec, section->sh_name); + return object_error::success; } // Use the default symbol table name section. - return getString(dot_strtab_sec, symb->st_name); + Result = getString(dot_strtab_sec, symb->st_name); + return object_error::success; } template -uint64_t ELFObjectFile - ::getSymbolAddress(DataRefImpl Symb) const { +error_code ELFObjectFile + ::getSymbolAddress(DataRefImpl Symb, + uint64_t &Result) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); const Elf_Shdr *Section; switch (symb->st_shndx) { case ELF::SHN_COMMON: // Undefined symbols have no address yet. - case ELF::SHN_UNDEF: return UnknownAddressOrSize; - case ELF::SHN_ABS: return symb->st_value; + case ELF::SHN_UNDEF: + Result = UnknownAddressOrSize; + return object_error::success; + case ELF::SHN_ABS: + Result = symb->st_value; + return object_error::success; default: Section = getSection(symb->st_shndx); } switch (symb->getType()) { - case ELF::STT_SECTION: return Section ? Section->sh_addr - : UnknownAddressOrSize; + case ELF::STT_SECTION: + Result = Section ? Section->sh_addr : UnknownAddressOrSize; + return object_error::success; case ELF::STT_FUNC: case ELF::STT_OBJECT: case ELF::STT_NOTYPE: - return symb->st_value; - default: return UnknownAddressOrSize; + Result = symb->st_value; + return object_error::success; + default: + Result = UnknownAddressOrSize; + return object_error::success; } } template -uint64_t ELFObjectFile - ::getSymbolSize(DataRefImpl Symb) const { +error_code ELFObjectFile + ::getSymbolSize(DataRefImpl Symb, + uint64_t &Result) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); if (symb->st_size == 0) - return UnknownAddressOrSize; - return symb->st_size; + Result = UnknownAddressOrSize; + Result = symb->st_size; + return object_error::success; } template -char ELFObjectFile - ::getSymbolNMTypeChar(DataRefImpl Symb) const { +error_code ELFObjectFile + ::getSymbolNMTypeChar(DataRefImpl Symb, + char &Result) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); const Elf_Shdr *Section = getSection(symb->st_shndx); @@ -390,71 +408,91 @@ char ELFObjectFile ret = 'W'; } - if (ret == '?' && symb->getType() == ELF::STT_SECTION) - return StringSwitch(getSymbolName(Symb)) + if (ret == '?' && symb->getType() == ELF::STT_SECTION) { + StringRef name; + if (error_code ec = getSymbolName(Symb, name)) + return ec; + Result = StringSwitch(name) .StartsWith(".debug", 'N') .StartsWith(".note", 'n'); + return object_error::success; + } - return ret; + Result = ret; + return object_error::success; } template -bool ELFObjectFile - ::isSymbolInternal(DataRefImpl Symb) const { +error_code ELFObjectFile + ::isSymbolInternal(DataRefImpl Symb, + bool &Result) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); if ( symb->getType() == ELF::STT_FILE || symb->getType() == ELF::STT_SECTION) - return true; - return false; + Result = true; + Result = false; + return object_error::success; } template -SectionRef ELFObjectFile - ::getSectionNext(DataRefImpl Sec) const { +error_code ELFObjectFile + ::getSectionNext(DataRefImpl Sec, SectionRef &Result) const { const uint8_t *sec = reinterpret_cast(Sec.p); sec += Header->e_shentsize; Sec.p = reinterpret_cast(sec); - return SectionRef(Sec, this); + Result = SectionRef(Sec, this); + return object_error::success; } template -StringRef ELFObjectFile - ::getSectionName(DataRefImpl Sec) const { +error_code ELFObjectFile + ::getSectionName(DataRefImpl Sec, + StringRef &Result) const { const Elf_Shdr *sec = reinterpret_cast(Sec.p); - return StringRef(getString(dot_shstrtab_sec, sec->sh_name)); + Result = StringRef(getString(dot_shstrtab_sec, sec->sh_name)); + return object_error::success; } template -uint64_t ELFObjectFile - ::getSectionAddress(DataRefImpl Sec) const { +error_code ELFObjectFile + ::getSectionAddress(DataRefImpl Sec, + uint64_t &Result) const { const Elf_Shdr *sec = reinterpret_cast(Sec.p); - return sec->sh_addr; + Result = sec->sh_addr; + return object_error::success; } template -uint64_t ELFObjectFile - ::getSectionSize(DataRefImpl Sec) const { +error_code ELFObjectFile + ::getSectionSize(DataRefImpl Sec, + uint64_t &Result) const { const Elf_Shdr *sec = reinterpret_cast(Sec.p); - return sec->sh_size; + Result = sec->sh_size; + return object_error::success; } template -StringRef ELFObjectFile - ::getSectionContents(DataRefImpl Sec) const { +error_code ELFObjectFile + ::getSectionContents(DataRefImpl Sec, + StringRef &Result) const { const Elf_Shdr *sec = reinterpret_cast(Sec.p); - const char *start = (char*)base() + sec->sh_offset; - return StringRef(start, sec->sh_size); + const char *start = (const char*)base() + sec->sh_offset; + Result = StringRef(start, sec->sh_size); + return object_error::success; } template -bool ELFObjectFile - ::isSectionText(DataRefImpl Sec) const { +error_code ELFObjectFile + ::isSectionText(DataRefImpl Sec, + bool &Result) const { const Elf_Shdr *sec = reinterpret_cast(Sec.p); if (sec->sh_flags & ELF::SHF_EXECINSTR) - return true; - return false; + Result = true; + else + Result = false; + return object_error::success; } template diff --git a/lib/Object/Error.cpp b/lib/Object/Error.cpp index 40f97d4..2594625 100644 --- a/lib/Object/Error.cpp +++ b/lib/Object/Error.cpp @@ -37,6 +37,8 @@ std::string _object_error_category::message(int ev) const { return "The file was not recognized as a valid object file"; case object_error::parse_failed: return "Invalid data was encountered while parsing the file"; + case object_error::unexpected_eof: + return "The end of the file was unexpectedly encountered"; default: llvm_unreachable("An enumerator of object_error does not have a message " "defined."); diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 3b76c6f..71f1f8c 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -47,19 +47,19 @@ public: virtual unsigned getArch() const; protected: - virtual SymbolRef getSymbolNext(DataRefImpl Symb) const; - virtual StringRef getSymbolName(DataRefImpl Symb) const; - virtual uint64_t getSymbolAddress(DataRefImpl Symb) const; - virtual uint64_t getSymbolSize(DataRefImpl Symb) const; - virtual char getSymbolNMTypeChar(DataRefImpl Symb) const; - virtual bool isSymbolInternal(DataRefImpl Symb) const; - - virtual SectionRef getSectionNext(DataRefImpl Sec) const; - virtual StringRef getSectionName(DataRefImpl Sec) const; - virtual uint64_t getSectionAddress(DataRefImpl Sec) const; - virtual uint64_t getSectionSize(DataRefImpl Sec) const; - virtual StringRef getSectionContents(DataRefImpl Sec) const; - virtual bool isSectionText(DataRefImpl Sec) const; + virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; + virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; + virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; + virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; + virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const; + virtual error_code isSymbolInternal(DataRefImpl Symb, bool &Res) const; + + virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const; + virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const; + virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const; + virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const; + virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const; + virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const; private: MachOObject *MachOObj; @@ -115,29 +115,38 @@ void MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI, } -SymbolRef MachOObjectFile::getSymbolNext(DataRefImpl DRI) const { +error_code MachOObjectFile::getSymbolNext(DataRefImpl DRI, + SymbolRef &Result) const { DRI.d.b++; moveToNextSymbol(DRI); - return SymbolRef(DRI, this); + Result = SymbolRef(DRI, this); + return object_error::success; } -StringRef MachOObjectFile::getSymbolName(DataRefImpl DRI) const { +error_code MachOObjectFile::getSymbolName(DataRefImpl DRI, + StringRef &Result) const { InMemoryStruct Entry; getSymbolTableEntry(DRI, Entry); - return MachOObj->getStringAtIndex(Entry->StringIndex); + Result = MachOObj->getStringAtIndex(Entry->StringIndex); + return object_error::success; } -uint64_t MachOObjectFile::getSymbolAddress(DataRefImpl DRI) const { +error_code MachOObjectFile::getSymbolAddress(DataRefImpl DRI, + uint64_t &Result) const { InMemoryStruct Entry; getSymbolTableEntry(DRI, Entry); - return Entry->Value; + Result = Entry->Value; + return object_error::success; } -uint64_t MachOObjectFile::getSymbolSize(DataRefImpl DRI) const { - return UnknownAddressOrSize; +error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, + uint64_t &Result) const { + Result = UnknownAddressOrSize; + return object_error::success; } -char MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI) const { +error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI, + char &Result) const { InMemoryStruct Entry; getSymbolTableEntry(DRI, Entry); @@ -157,13 +166,16 @@ char MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI) const { if (Entry->Flags & (macho::STF_External | macho::STF_PrivateExtern)) Char = toupper(Char); - return Char; + Result = Char; + return object_error::success; } -bool MachOObjectFile::isSymbolInternal(DataRefImpl DRI) const { +error_code MachOObjectFile::isSymbolInternal(DataRefImpl DRI, + bool &Result) const { InMemoryStruct Entry; getSymbolTableEntry(DRI, Entry); - return Entry->Flags & macho::STF_StabsEntryMask; + Result = Entry->Flags & macho::STF_StabsEntryMask; + return object_error::success; } ObjectFile::symbol_iterator MachOObjectFile::begin_symbols() const { @@ -205,10 +217,12 @@ void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const { } } -SectionRef MachOObjectFile::getSectionNext(DataRefImpl DRI) const { +error_code MachOObjectFile::getSectionNext(DataRefImpl DRI, + SectionRef &Result) const { DRI.d.b++; moveToNextSection(DRI); - return SectionRef(DRI, this); + Result = SectionRef(DRI, this); + return object_error::success; } void @@ -220,43 +234,53 @@ MachOObjectFile::getSection(DataRefImpl DRI, MachOObj->ReadSection(LCI, DRI.d.b, Res); } -StringRef MachOObjectFile::getSectionName(DataRefImpl DRI) const { +error_code MachOObjectFile::getSectionName(DataRefImpl DRI, + StringRef &Result) const { InMemoryStruct SLC; LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); MachOObj->ReadSegmentLoadCommand(LCI, SLC); InMemoryStruct Sect; MachOObj->ReadSection(LCI, DRI.d.b, Sect); - static char Result[34]; - strcpy(Result, SLC->Name); - strcat(Result, ","); - strcat(Result, Sect->Name); - return StringRef(Result); + static char result[34]; + strcpy(result, SLC->Name); + strcat(result, ","); + strcat(result, Sect->Name); + Result = StringRef(result); + return object_error::success; } -uint64_t MachOObjectFile::getSectionAddress(DataRefImpl DRI) const { +error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI, + uint64_t &Result) const { InMemoryStruct Sect; getSection(DRI, Sect); - return Sect->Address; + Result = Sect->Address; + return object_error::success; } -uint64_t MachOObjectFile::getSectionSize(DataRefImpl DRI) const { +error_code MachOObjectFile::getSectionSize(DataRefImpl DRI, + uint64_t &Result) const { InMemoryStruct Sect; getSection(DRI, Sect); - return Sect->Size; + Result = Sect->Size; + return object_error::success; } -StringRef MachOObjectFile::getSectionContents(DataRefImpl DRI) const { +error_code MachOObjectFile::getSectionContents(DataRefImpl DRI, + StringRef &Result) const { InMemoryStruct Sect; getSection(DRI, Sect); - return MachOObj->getData(Sect->Offset, Sect->Size); + Result = MachOObj->getData(Sect->Offset, Sect->Size); + return object_error::success; } -bool MachOObjectFile::isSectionText(DataRefImpl DRI) const { +error_code MachOObjectFile::isSectionText(DataRefImpl DRI, + bool &Result) const { InMemoryStruct SLC; LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); MachOObj->ReadSegmentLoadCommand(LCI, SLC); - return !strcmp(SLC->Name, "__TEXT"); + Result = !strcmp(SLC->Name, "__TEXT"); + return object_error::success; } ObjectFile::section_iterator MachOObjectFile::begin_sections() const { diff --git a/lib/Object/Object.cpp b/lib/Object/Object.cpp index 603b23c..9a373ad 100644 --- a/lib/Object/Object.cpp +++ b/lib/Object/Object.cpp @@ -41,19 +41,28 @@ LLVMBool LLVMIsSectionIteratorAtEnd(LLVMObjectFileRef ObjectFile, } void LLVMMoveToNextSection(LLVMSectionIteratorRef SI) { - // We can't use unwrap() here because the argument to ++ must be an lvalue. - ++*reinterpret_cast(SI); + error_code ec; + unwrap(SI)->increment(ec); + if (ec) report_fatal_error("LLVMMoveToNextSection failed: " + ec.message()); } const char *LLVMGetSectionName(LLVMSectionIteratorRef SI) { - return (*unwrap(SI))->getName().data(); + StringRef ret; + if (error_code ec = (*unwrap(SI))->getName(ret)) + report_fatal_error(ec.message()); + return ret.data(); } uint64_t LLVMGetSectionSize(LLVMSectionIteratorRef SI) { - return (*unwrap(SI))->getSize(); + uint64_t ret; + if (error_code ec = (*unwrap(SI))->getSize(ret)) + report_fatal_error(ec.message()); + return ret; } const char *LLVMGetSectionContents(LLVMSectionIteratorRef SI) { - return (*unwrap(SI))->getContents().data(); + StringRef ret; + if (error_code ec = (*unwrap(SI))->getContents(ret)) + report_fatal_error(ec.message()); + return ret.data(); } - diff --git a/tools/llvm-nm/llvm-nm.cpp b/tools/llvm-nm/llvm-nm.cpp index f6eb33c..014cb29 100644 --- a/tools/llvm-nm/llvm-nm.cpp +++ b/tools/llvm-nm/llvm-nm.cpp @@ -143,6 +143,14 @@ namespace { StringRef CurrentFilename; typedef std::vector SymbolListT; SymbolListT SymbolList; + + bool error(error_code ec) { + if (!ec) return false; + + outs() << ToolName << ": error reading file: " << ec.message() << ".\n"; + outs().flush(); + return true; + } } static void SortAndPrintSymbolList() { @@ -261,19 +269,25 @@ static void DumpSymbolNamesFromModule(Module *M) { } static void DumpSymbolNamesFromObject(ObjectFile *obj) { + error_code ec; for (ObjectFile::symbol_iterator i = obj->begin_symbols(), - e = obj->end_symbols(); i != e; ++i) { - if (!DebugSyms && i->isInternal()) + e = obj->end_symbols(); + i != e; i.increment(ec)) { + if (error(ec)) break; + bool internal; + if (error(i->isInternal(internal))) break; + if (!DebugSyms && internal) continue; NMSymbol s; s.Size = object::UnknownAddressOrSize; s.Address = object::UnknownAddressOrSize; - if (PrintSize || SizeSort) - s.Size = i->getSize(); + if (PrintSize || SizeSort) { + if (error(i->getSize(s.Size))) break; + } if (PrintAddress) - s.Address = i->getAddress(); - s.TypeChar = i->getNMTypeChar(); - s.Name = i->getName(); + if (error(i->getAddress(s.Address))) break; + if (error(i->getNMTypeChar(s.TypeChar))) break; + if (error(i->getName(s.Name))) break; SymbolList.push_back(s); } diff --git a/tools/llvm-objdump/llvm-objdump.cpp b/tools/llvm-objdump/llvm-objdump.cpp index a17624a..c971e49 100644 --- a/tools/llvm-objdump/llvm-objdump.cpp +++ b/tools/llvm-objdump/llvm-objdump.cpp @@ -69,6 +69,14 @@ namespace { "see -version for available targets")); StringRef ToolName; + + bool error(error_code ec) { + if (!ec) return false; + + outs() << ToolName << ": error reading file: " << ec.message() << ".\n"; + outs().flush(); + return true; + } } static const Target *GetTarget(const ObjectFile *Obj = NULL) { @@ -161,12 +169,18 @@ static void DisassembleInput(const StringRef &Filename) { outs() << Filename << ":\tfile format " << Obj->getFileFormatName() << "\n\n\n"; + error_code ec; for (ObjectFile::section_iterator i = Obj->begin_sections(), e = Obj->end_sections(); - i != e; ++i) { - if (!i->isText()) - continue; - outs() << "Disassembly of section " << i->getName() << ":\n\n"; + i != e; i.increment(ec)) { + if (error(ec)) break; + bool text; + if (error(i->isText(text))) break; + if (!text) continue; + + StringRef name; + if (error(i->getName(name))) break; + outs() << "Disassembly of section " << name << ":\n\n"; // Set up disassembler. OwningPtr AsmInfo(TheTarget->createAsmInfo(TripleName)); @@ -202,7 +216,8 @@ static void DisassembleInput(const StringRef &Filename) { return; } - StringRef Bytes = i->getContents(); + StringRef Bytes; + if (error(i->getContents(Bytes))) break; StringRefMemoryObject memoryObject(Bytes); uint64_t Size; uint64_t Index; @@ -217,7 +232,9 @@ static void DisassembleInput(const StringRef &Filename) { # endif if (DisAsm->getInstruction(Inst, Size, memoryObject, Index, DebugOut)) { - outs() << format("%8x:\t", i->getAddress() + Index); + uint64_t addr; + if (error(i->getAddress(addr))) break; + outs() << format("%8x:\t", addr + Index); DumpBytes(StringRef(Bytes.data() + Index, Size)); IP->printInst(&Inst, outs()); outs() << "\n"; -- cgit v1.1 From 84149460d5fa2503e953f5800e7cdbf88f161b5a Mon Sep 17 00:00:00 2001 From: Dan Bailey Date: Sat, 25 Jun 2011 18:16:28 +0000 Subject: PTX: Reverting implementation of i8. The .b8 operations in PTX are far more limiting than I first thought. The mov operation isn't even supported, so there's no way of converting a .pred value into a .b8 without going via .b16, which is not sensible. An improved implementation needs to use the fact that loads and stores automatically extend and truncate to implement support for EXTLOAD and TRUNCSTORE in order to correctly support boolean values. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133873 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/PTX/PTXAsmPrinter.cpp | 2 - lib/Target/PTX/PTXCallingConv.td | 2 - lib/Target/PTX/PTXISelLowering.cpp | 74 +++++++++--------- lib/Target/PTX/PTXInstrInfo.cpp | 9 +-- lib/Target/PTX/PTXInstrInfo.td | 121 ++++++------------------------ lib/Target/PTX/PTXRegisterInfo.td | 132 --------------------------------- lib/Target/PTX/generate-register-td.py | 29 ++------ test/CodeGen/PTX/cvt.ll | 83 --------------------- test/CodeGen/PTX/ld.ll | 77 ------------------- test/CodeGen/PTX/mov.ll | 12 --- test/CodeGen/PTX/st.ll | 78 ------------------- 11 files changed, 73 insertions(+), 546 deletions(-) diff --git a/lib/Target/PTX/PTXAsmPrinter.cpp b/lib/Target/PTX/PTXAsmPrinter.cpp index c9b2915..2848d54 100644 --- a/lib/Target/PTX/PTXAsmPrinter.cpp +++ b/lib/Target/PTX/PTXAsmPrinter.cpp @@ -92,7 +92,6 @@ static const char *getRegisterTypeName(unsigned RegNo) { #define TEST_REGCLS(cls, clsstr) \ if (PTX::cls ## RegisterClass->contains(RegNo)) return # clsstr; TEST_REGCLS(RegPred, pred); - TEST_REGCLS(RegI8, b8); TEST_REGCLS(RegI16, b16); TEST_REGCLS(RegI32, b32); TEST_REGCLS(RegI64, b64); @@ -125,7 +124,6 @@ static const char *getTypeName(const Type* type) { case Type::IntegerTyID: switch (type->getPrimitiveSizeInBits()) { default: llvm_unreachable("Unknown integer bit-width"); - case 8: return ".u8"; case 16: return ".u16"; case 32: return ".u32"; case 64: return ".u64"; diff --git a/lib/Target/PTX/PTXCallingConv.td b/lib/Target/PTX/PTXCallingConv.td index 2de6199..3e3ff48 100644 --- a/lib/Target/PTX/PTXCallingConv.td +++ b/lib/Target/PTX/PTXCallingConv.td @@ -15,7 +15,6 @@ // PTX Formal Parameter Calling Convention def CC_PTX : CallingConv<[ CCIfType<[i1], CCAssignToReg<[P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122, P123, P124, P125, P126, P127]>>, - CCIfType<[i8], CCAssignToReg<[RQ12, RQ13, RQ14, RQ15, RQ16, RQ17, RQ18, RQ19, RQ20, RQ21, RQ22, RQ23, RQ24, RQ25, RQ26, RQ27, RQ28, RQ29, RQ30, RQ31, RQ32, RQ33, RQ34, RQ35, RQ36, RQ37, RQ38, RQ39, RQ40, RQ41, RQ42, RQ43, RQ44, RQ45, RQ46, RQ47, RQ48, RQ49, RQ50, RQ51, RQ52, RQ53, RQ54, RQ55, RQ56, RQ57, RQ58, RQ59, RQ60, RQ61, RQ62, RQ63, RQ64, RQ65, RQ66, RQ67, RQ68, RQ69, RQ70, RQ71, RQ72, RQ73, RQ74, RQ75, RQ76, RQ77, RQ78, RQ79, RQ80, RQ81, RQ82, RQ83, RQ84, RQ85, RQ86, RQ87, RQ88, RQ89, RQ90, RQ91, RQ92, RQ93, RQ94, RQ95, RQ96, RQ97, RQ98, RQ99, RQ100, RQ101, RQ102, RQ103, RQ104, RQ105, RQ106, RQ107, RQ108, RQ109, RQ110, RQ111, RQ112, RQ113, RQ114, RQ115, RQ116, RQ117, RQ118, RQ119, RQ120, RQ121, RQ122, RQ123, RQ124, RQ125, RQ126, RQ127]>>, CCIfType<[i16], CCAssignToReg<[RH12, RH13, RH14, RH15, RH16, RH17, RH18, RH19, RH20, RH21, RH22, RH23, RH24, RH25, RH26, RH27, RH28, RH29, RH30, RH31, RH32, RH33, RH34, RH35, RH36, RH37, RH38, RH39, RH40, RH41, RH42, RH43, RH44, RH45, RH46, RH47, RH48, RH49, RH50, RH51, RH52, RH53, RH54, RH55, RH56, RH57, RH58, RH59, RH60, RH61, RH62, RH63, RH64, RH65, RH66, RH67, RH68, RH69, RH70, RH71, RH72, RH73, RH74, RH75, RH76, RH77, RH78, RH79, RH80, RH81, RH82, RH83, RH84, RH85, RH86, RH87, RH88, RH89, RH90, RH91, RH92, RH93, RH94, RH95, RH96, RH97, RH98, RH99, RH100, RH101, RH102, RH103, RH104, RH105, RH106, RH107, RH108, RH109, RH110, RH111, RH112, RH113, RH114, RH115, RH116, RH117, RH118, RH119, RH120, RH121, RH122, RH123, RH124, RH125, RH126, RH127]>>, CCIfType<[i32,f32], CCAssignToReg<[R12, R13, R14, R15, R16, R17, R18, R19, R20, R21, R22, R23, R24, R25, R26, R27, R28, R29, R30, R31, R32, R33, R34, R35, R36, R37, R38, R39, R40, R41, R42, R43, R44, R45, R46, R47, R48, R49, R50, R51, R52, R53, R54, R55, R56, R57, R58, R59, R60, R61, R62, R63, R64, R65, R66, R67, R68, R69, R70, R71, R72, R73, R74, R75, R76, R77, R78, R79, R80, R81, R82, R83, R84, R85, R86, R87, R88, R89, R90, R91, R92, R93, R94, R95, R96, R97, R98, R99, R100, R101, R102, R103, R104, R105, R106, R107, R108, R109, R110, R111, R112, R113, R114, R115, R116, R117, R118, R119, R120, R121, R122, R123, R124, R125, R126, R127]>>, CCIfType<[i64,f64], CCAssignToReg<[RD12, RD13, RD14, RD15, RD16, RD17, RD18, RD19, RD20, RD21, RD22, RD23, RD24, RD25, RD26, RD27, RD28, RD29, RD30, RD31, RD32, RD33, RD34, RD35, RD36, RD37, RD38, RD39, RD40, RD41, RD42, RD43, RD44, RD45, RD46, RD47, RD48, RD49, RD50, RD51, RD52, RD53, RD54, RD55, RD56, RD57, RD58, RD59, RD60, RD61, RD62, RD63, RD64, RD65, RD66, RD67, RD68, RD69, RD70, RD71, RD72, RD73, RD74, RD75, RD76, RD77, RD78, RD79, RD80, RD81, RD82, RD83, RD84, RD85, RD86, RD87, RD88, RD89, RD90, RD91, RD92, RD93, RD94, RD95, RD96, RD97, RD98, RD99, RD100, RD101, RD102, RD103, RD104, RD105, RD106, RD107, RD108, RD109, RD110, RD111, RD112, RD113, RD114, RD115, RD116, RD117, RD118, RD119, RD120, RD121, RD122, RD123, RD124, RD125, RD126, RD127]>> @@ -24,7 +23,6 @@ def CC_PTX : CallingConv<[ // PTX Return Value Calling Convention def RetCC_PTX : CallingConv<[ CCIfType<[i1], CCAssignToReg<[P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11]>>, - CCIfType<[i8], CCAssignToReg<[RQ0, RQ1, RQ2, RQ3, RQ4, RQ5, RQ6, RQ7, RQ8, RQ9, RQ10, RQ11]>>, CCIfType<[i16], CCAssignToReg<[RH0, RH1, RH2, RH3, RH4, RH5, RH6, RH7, RH8, RH9, RH10, RH11]>>, CCIfType<[i32,f32], CCAssignToReg<[R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11]>>, CCIfType<[i64,f64], CCAssignToReg<[RD0, RD1, RD2, RD3, RD4, RD5, RD6, RD7, RD8, RD9, RD10, RD11]>> diff --git a/lib/Target/PTX/PTXISelLowering.cpp b/lib/Target/PTX/PTXISelLowering.cpp index 9b836a5..7831aa0 100644 --- a/lib/Target/PTX/PTXISelLowering.cpp +++ b/lib/Target/PTX/PTXISelLowering.cpp @@ -40,7 +40,6 @@ PTXTargetLowering::PTXTargetLowering(TargetMachine &TM) : TargetLowering(TM, new TargetLoweringObjectFileELF()) { // Set up the register classes. addRegisterClass(MVT::i1, PTX::RegPredRegisterClass); - addRegisterClass(MVT::i8, PTX::RegI8RegisterClass); addRegisterClass(MVT::i16, PTX::RegI16RegisterClass); addRegisterClass(MVT::i32, PTX::RegI32RegisterClass); addRegisterClass(MVT::i64, PTX::RegI64RegisterClass); @@ -48,48 +47,59 @@ PTXTargetLowering::PTXTargetLowering(TargetMachine &TM) addRegisterClass(MVT::f64, PTX::RegF64RegisterClass); setBooleanContents(ZeroOrOneBooleanContent); - - setOperationAction(ISD::EXCEPTIONADDR, MVT::i32, Expand); - - setOperationAction(ISD::ConstantFP, MVT::f32, Legal); - setOperationAction(ISD::ConstantFP, MVT::f64, Legal); - - // Promote i1 type - setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote); - setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote); - setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote); + setMinFunctionAlignment(2); - setTruncStoreAction(MVT::i8, MVT::i1, Promote); + //////////////////////////////////// + /////////// Expansion ////////////// + //////////////////////////////////// - setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); + // (any/zero/sign) extload => load + (any/zero/sign) extend - // Turn i16 (z)extload into load + (z)extend setLoadExtAction(ISD::EXTLOAD, MVT::i16, Expand); setLoadExtAction(ISD::ZEXTLOAD, MVT::i16, Expand); setLoadExtAction(ISD::SEXTLOAD, MVT::i16, Expand); - - // Turn f32 extload into load + fextend - setLoadExtAction(ISD::EXTLOAD, MVT::f32, Expand); - - // Turn f64 truncstore into trunc + store. - setTruncStoreAction(MVT::f64, MVT::f32, Expand); - - // Customize translation of memory addresses - setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); - setOperationAction(ISD::GlobalAddress, MVT::i64, Custom); - - // Expand BR_CC into BRCOND + + // f32 extload => load + fextend + + setLoadExtAction(ISD::EXTLOAD, MVT::f32, Expand); + + // f64 truncstore => trunc + store + + setTruncStoreAction(MVT::f64, MVT::f32, Expand); + + // sign_extend_inreg => sign_extend + + setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); + + // br_cc => brcond + setOperationAction(ISD::BR_CC, MVT::Other, Expand); - // Expand SELECT_CC into SETCC + // select_cc => setcc + setOperationAction(ISD::SELECT_CC, MVT::Other, Expand); setOperationAction(ISD::SELECT_CC, MVT::f32, Expand); setOperationAction(ISD::SELECT_CC, MVT::f64, Expand); - - // need to lower SETCC of RegPred into bitwise logic + + //////////////////////////////////// + //////////// Legal ///////////////// + //////////////////////////////////// + + setOperationAction(ISD::ConstantFP, MVT::f32, Legal); + setOperationAction(ISD::ConstantFP, MVT::f64, Legal); + + //////////////////////////////////// + //////////// Custom //////////////// + //////////////////////////////////// + + // customise setcc to use bitwise logic if possible + setOperationAction(ISD::SETCC, MVT::i1, Custom); - setMinFunctionAlignment(2); + // customize translation of memory addresses + + setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); + setOperationAction(ISD::GlobalAddress, MVT::i64, Custom); // Compute derived properties from the register classes computeRegisterProperties(); @@ -187,7 +197,6 @@ struct argmap_entry { bool operator==(MVT::SimpleValueType _VT) const { return VT == _VT; } } argmap[] = { argmap_entry(MVT::i1, PTX::RegPredRegisterClass), - argmap_entry(MVT::i8, PTX::RegI8RegisterClass), argmap_entry(MVT::i16, PTX::RegI16RegisterClass), argmap_entry(MVT::i32, PTX::RegI32RegisterClass), argmap_entry(MVT::i64, PTX::RegI64RegisterClass), @@ -264,9 +273,6 @@ SDValue PTXTargetLowering:: if (RegVT == MVT::i1) { TRC = PTX::RegPredRegisterClass; } - else if (RegVT == MVT::i8) { - TRC = PTX::RegI8RegisterClass; - } else if (RegVT == MVT::i16) { TRC = PTX::RegI16RegisterClass; } diff --git a/lib/Target/PTX/PTXInstrInfo.cpp b/lib/Target/PTX/PTXInstrInfo.cpp index 720d5b1..5bdac89 100644 --- a/lib/Target/PTX/PTXInstrInfo.cpp +++ b/lib/Target/PTX/PTXInstrInfo.cpp @@ -33,7 +33,6 @@ static const struct map_entry { const TargetRegisterClass *cls; const int opcode; } map[] = { - { &PTX::RegI8RegClass, PTX::MOVU8rr }, { &PTX::RegI16RegClass, PTX::MOVU16rr }, { &PTX::RegI32RegClass, PTX::MOVU32rr }, { &PTX::RegI64RegClass, PTX::MOVU64rr }, @@ -303,9 +302,7 @@ void PTXInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, int OpCode; // Select the appropriate opcode based on the register class - if (RC == PTX::RegI8RegisterClass) { - OpCode = PTX::STACKSTOREI8; - } else if (RC == PTX::RegI16RegisterClass) { + if (RC == PTX::RegI16RegisterClass) { OpCode = PTX::STACKSTOREI16; } else if (RC == PTX::RegI32RegisterClass) { OpCode = PTX::STACKSTOREI32; @@ -340,9 +337,7 @@ void PTXInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, int OpCode; // Select the appropriate opcode based on the register class - if (RC == PTX::RegI8RegisterClass) { - OpCode = PTX::STACKLOADI8; - } else if (RC == PTX::RegI16RegisterClass) { + if (RC == PTX::RegI16RegisterClass) { OpCode = PTX::STACKLOADI16; } else if (RC == PTX::RegI32RegisterClass) { OpCode = PTX::STACKLOADI32; diff --git a/lib/Target/PTX/PTXInstrInfo.td b/lib/Target/PTX/PTXInstrInfo.td index c5cedb0..6bfe906 100644 --- a/lib/Target/PTX/PTXInstrInfo.td +++ b/lib/Target/PTX/PTXInstrInfo.td @@ -537,7 +537,6 @@ multiclass PTX_LD { - defm u8 : PTX_LD; defm u16 : PTX_LD; defm u32 : PTX_LD; defm u64 : PTX_LD; @@ -573,7 +572,6 @@ multiclass PTX_ST { - defm u8 : PTX_ST; defm u16 : PTX_ST; defm u32 : PTX_ST; defm u64 : PTX_ST; @@ -785,27 +783,22 @@ defm XOR : PTX_LOGIC<"xor", xor>; let neverHasSideEffects = 1 in { def MOVPREDrr : InstPTX<(outs RegPred:$d), (ins RegPred:$a), "mov.pred\t$d, $a", []>; - def MOVU8rr - : InstPTX<(outs RegI8:$d), (ins RegI8:$a), "mov.u8\t$d, $a", []>; def MOVU16rr - : InstPTX<(outs RegI16:$d), (ins RegI16:$a), "mov.u16\t$d, $a", []>; + : InstPTX<(outs RegI16:$d), (ins RegI16:$a), "mov.u16\t$d, $a", []>; def MOVU32rr - : InstPTX<(outs RegI32:$d), (ins RegI32:$a), "mov.u32\t$d, $a", []>; + : InstPTX<(outs RegI32:$d), (ins RegI32:$a), "mov.u32\t$d, $a", []>; def MOVU64rr - : InstPTX<(outs RegI64:$d), (ins RegI64:$a), "mov.u64\t$d, $a", []>; + : InstPTX<(outs RegI64:$d), (ins RegI64:$a), "mov.u64\t$d, $a", []>; def MOVF32rr - : InstPTX<(outs RegF32:$d), (ins RegF32:$a), "mov.f32\t$d, $a", []>; + : InstPTX<(outs RegF32:$d), (ins RegF32:$a), "mov.f32\t$d, $a", []>; def MOVF64rr - : InstPTX<(outs RegF64:$d), (ins RegF64:$a), "mov.f64\t$d, $a", []>; + : InstPTX<(outs RegF64:$d), (ins RegF64:$a), "mov.f64\t$d, $a", []>; } let isReMaterializable = 1, isAsCheapAsAMove = 1 in { def MOVPREDri : InstPTX<(outs RegPred:$d), (ins i1imm:$a), "mov.pred\t$d, $a", [(set RegPred:$d, imm:$a)]>; - def MOVU8ri - : InstPTX<(outs RegI8:$d), (ins i8imm:$a), "mov.u8\t$d, $a", - [(set RegI8:$d, imm:$a)]>; def MOVU16ri : InstPTX<(outs RegI16:$d), (ins i16imm:$a), "mov.u16\t$d, $a", [(set RegI16:$d, imm:$a)]>; @@ -845,9 +838,6 @@ let hasSideEffects = 1 in { def LDpiPred : InstPTX<(outs RegPred:$d), (ins MEMpi:$a), "ld.param.pred\t$d, [$a]", [(set RegPred:$d, (PTXloadparam timm:$a))]>; - def LDpiU8 : InstPTX<(outs RegI8:$d), (ins MEMpi:$a), - "ld.param.u8\t$d, [$a]", - [(set RegI8:$d, (PTXloadparam timm:$a))]>; def LDpiU16 : InstPTX<(outs RegI16:$d), (ins MEMpi:$a), "ld.param.u16\t$d, [$a]", [(set RegI16:$d, (PTXloadparam timm:$a))]>; @@ -867,9 +857,6 @@ let hasSideEffects = 1 in { def STpiPred : InstPTX<(outs), (ins MEMret:$d, RegPred:$a), "st.param.pred\t[$d], $a", [(PTXstoreparam timm:$d, RegPred:$a)]>; - def STpiU8 : InstPTX<(outs), (ins MEMret:$d, RegI8:$a), - "st.param.u8\t[$d], $a", - [(PTXstoreparam timm:$d, RegI8:$a)]>; def STpiU16 : InstPTX<(outs), (ins MEMret:$d, RegI16:$a), "st.param.u16\t[$d], $a", [(PTXstoreparam timm:$d, RegI16:$a)]>; @@ -900,62 +887,34 @@ defm STs : PTX_ST_ALL<"st.shared", store_shared>; // PTX does not directly support converting to a predicate type, so we fake it // by performing a greater-than test between the value and zero. This follows // the C convention that any non-zero value is equivalent to 'true'. -def CVT_pred_u8 - : InstPTX<(outs RegPred:$d), (ins RegI8:$a), "setp.gt.b8\t$d, $a, 0", - [(set RegPred:$d, (trunc RegI8:$a))]>; - def CVT_pred_u16 - : InstPTX<(outs RegPred:$d), (ins RegI16:$a), "setp.gt.b16\t$d, $a, 0", + : InstPTX<(outs RegPred:$d), (ins RegI16:$a), "setp.gt.u16\t$d, $a, 0", [(set RegPred:$d, (trunc RegI16:$a))]>; def CVT_pred_u32 - : InstPTX<(outs RegPred:$d), (ins RegI32:$a), "setp.gt.b32\t$d, $a, 0", + : InstPTX<(outs RegPred:$d), (ins RegI32:$a), "setp.gt.u32\t$d, $a, 0", [(set RegPred:$d, (trunc RegI32:$a))]>; def CVT_pred_u64 - : InstPTX<(outs RegPred:$d), (ins RegI64:$a), "setp.gt.b64\t$d, $a, 0", + : InstPTX<(outs RegPred:$d), (ins RegI64:$a), "setp.gt.u64\t$d, $a, 0", [(set RegPred:$d, (trunc RegI64:$a))]>; def CVT_pred_f32 - : InstPTX<(outs RegPred:$d), (ins RegF32:$a), "setp.gt.b32\t$d, $a, 0", + : InstPTX<(outs RegPred:$d), (ins RegF32:$a), "setp.gt.f32\t$d, $a, 0", [(set RegPred:$d, (fp_to_uint RegF32:$a))]>; def CVT_pred_f64 - : InstPTX<(outs RegPred:$d), (ins RegF64:$a), "setp.gt.b64\t$d, $a, 0", + : InstPTX<(outs RegPred:$d), (ins RegF64:$a), "setp.gt.f64\t$d, $a, 0", [(set RegPred:$d, (fp_to_uint RegF64:$a))]>; -// Conversion to u8 -// PTX does not directly support converting a predicate to a value, so we -// use a select instruction to select either 0 or 1 (integer or fp) based -// on the truth value of the predicate. -def CVT_u8_pred - : InstPTX<(outs RegI8:$d), (ins RegPred:$a), "selp.u8\t$d, 1, 0, $a", - [(set RegI8:$d, (zext RegPred:$a))]>; - -def CVT_u8_preds - : InstPTX<(outs RegI8:$d), (ins RegPred:$a), "selp.u8\t$d, 1, 0, $a", - [(set RegI8:$d, (sext RegPred:$a))]>; - -def CVT_u8_u32 - : InstPTX<(outs RegI8:$d), (ins RegI32:$a), "cvt.u8.u32\t$d, $a", - [(set RegI8:$d, (trunc RegI32:$a))]>; - -def CVT_u8_u64 - : InstPTX<(outs RegI8:$d), (ins RegI64:$a), "cvt.u8.u64\t$d, $a", - [(set RegI8:$d, (trunc RegI64:$a))]>; - -def CVT_u8_f32 - : InstPTX<(outs RegI8:$d), (ins RegF32:$a), "cvt.rzi.u8.f32\t$d, $a", - [(set RegI8:$d, (fp_to_uint RegF32:$a))]>; - -def CVT_u8_f64 - : InstPTX<(outs RegI8:$d), (ins RegF64:$a), "cvt.rzi.u8.f64\t$d, $a", - [(set RegI8:$d, (fp_to_uint RegF64:$a))]>; - // Conversion to u16 // PTX does not directly support converting a predicate to a value, so we // use a select instruction to select either 0 or 1 (integer or fp) based // on the truth value of the predicate. +def CVT_u16_preda + : InstPTX<(outs RegI16:$d), (ins RegPred:$a), "selp.u16\t$d, 1, 0, $a", + [(set RegI16:$d, (anyext RegPred:$a))]>; + def CVT_u16_pred : InstPTX<(outs RegI16:$d), (ins RegPred:$a), "selp.u16\t$d, 1, 0, $a", [(set RegI16:$d, (zext RegPred:$a))]>; @@ -964,14 +923,6 @@ def CVT_u16_preds : InstPTX<(outs RegI16:$d), (ins RegPred:$a), "selp.u16\t$d, 1, 0, $a", [(set RegI16:$d, (sext RegPred:$a))]>; -def CVT_u16_u8 - : InstPTX<(outs RegI16:$d), (ins RegI8:$a), "cvt.u16.u8\t$d, $a", - [(set RegI16:$d, (zext RegI8:$a))]>; - -def CVT_u16_s8 - : InstPTX<(outs RegI16:$d), (ins RegI8:$a), "cvt.u16.s8\t$d, $a", - [(set RegI16:$d, (sext RegI8:$a))]>; - def CVT_u16_u32 : InstPTX<(outs RegI16:$d), (ins RegI32:$a), "cvt.u16.u32\t$d, $a", [(set RegI16:$d, (trunc RegI32:$a))]>; @@ -994,9 +945,9 @@ def CVT_u32_pred : InstPTX<(outs RegI32:$d), (ins RegPred:$a), "selp.u32\t$d, 1, 0, $a", [(set RegI32:$d, (zext RegPred:$a))]>; -def CVT_u32_u8 - : InstPTX<(outs RegI32:$d), (ins RegI8:$a), "cvt.u32.u8\t$d, $a", - [(set RegI32:$d, (zext RegI8:$a))]>; +def CVT_u32_b16 + : InstPTX<(outs RegI32:$d), (ins RegI16:$a), "cvt.u32.u16\t$d, $a", + [(set RegI32:$d, (anyext RegI16:$a))]>; def CVT_u32_u16 : InstPTX<(outs RegI32:$d), (ins RegI16:$a), "cvt.u32.u16\t$d, $a", @@ -1006,10 +957,6 @@ def CVT_u32_preds : InstPTX<(outs RegI32:$d), (ins RegPred:$a), "selp.u32\t$d, 1, 0, $a", [(set RegI32:$d, (sext RegPred:$a))]>; -def CVT_u32_s8 - : InstPTX<(outs RegI32:$d), (ins RegI8:$a), "cvt.u32.s8\t$d, $a", - [(set RegI32:$d, (zext RegI8:$a))]>; - def CVT_u32_s16 : InstPTX<(outs RegI32:$d), (ins RegI16:$a), "cvt.u32.s16\t$d, $a", [(set RegI32:$d, (sext RegI16:$a))]>; @@ -1032,30 +979,22 @@ def CVT_u64_pred : InstPTX<(outs RegI64:$d), (ins RegPred:$a), "selp.u64\t$d, 1, 0, $a", [(set RegI64:$d, (zext RegPred:$a))]>; -def CVT_u64_u8 - : InstPTX<(outs RegI64:$d), (ins RegI8:$a), "cvt.u64.u8\t$d, $a", - [(set RegI64:$d, (zext RegI8:$a))]>; - -def CVT_u64_u16 - : InstPTX<(outs RegI64:$d), (ins RegI16:$a), "cvt.u64.u16\t$d, $a", - [(set RegI64:$d, (zext RegI16:$a))]>; - -def CVT_u64_u32 - : InstPTX<(outs RegI64:$d), (ins RegI32:$a), "cvt.u64.u32\t$d, $a", - [(set RegI64:$d, (zext RegI32:$a))]>; - def CVT_u64_preds : InstPTX<(outs RegI64:$d), (ins RegPred:$a), "selp.u64\t$d, 1, 0, $a", [(set RegI64:$d, (sext RegPred:$a))]>; -def CVT_u64_s8 - : InstPTX<(outs RegI64:$d), (ins RegI8:$a), "cvt.u64.s8\t$d, $a", - [(set RegI64:$d, (zext RegI8:$a))]>; +def CVT_u64_u16 + : InstPTX<(outs RegI64:$d), (ins RegI16:$a), "cvt.u64.u16\t$d, $a", + [(set RegI64:$d, (zext RegI16:$a))]>; def CVT_u64_s16 : InstPTX<(outs RegI64:$d), (ins RegI16:$a), "cvt.u64.s16\t$d, $a", [(set RegI64:$d, (sext RegI16:$a))]>; +def CVT_u64_u32 + : InstPTX<(outs RegI64:$d), (ins RegI32:$a), "cvt.u64.u32\t$d, $a", + [(set RegI64:$d, (zext RegI32:$a))]>; + def CVT_u64_s32 : InstPTX<(outs RegI64:$d), (ins RegI32:$a), "cvt.u64.s32\t$d, $a", [(set RegI64:$d, (sext RegI32:$a))]>; @@ -1075,10 +1014,6 @@ def CVT_f32_pred "selp.f32\t$d, 0F3F800000, 0F00000000, $a", // 1.0 [(set RegF32:$d, (uint_to_fp RegPred:$a))]>; -def CVT_f32_u8 - : InstPTX<(outs RegF32:$d), (ins RegI8:$a), "cvt.rn.f32.u8\t$d, $a", - [(set RegF32:$d, (uint_to_fp RegI8:$a))]>; - def CVT_f32_u16 : InstPTX<(outs RegF32:$d), (ins RegI16:$a), "cvt.rn.f32.u16\t$d, $a", [(set RegF32:$d, (uint_to_fp RegI16:$a))]>; @@ -1102,10 +1037,6 @@ def CVT_f64_pred "selp.f64\t$d, 0D3F80000000000000, 0D0000000000000000, $a", // 1.0 [(set RegF64:$d, (uint_to_fp RegPred:$a))]>; -def CVT_f64_u8 - : InstPTX<(outs RegF64:$d), (ins RegI8:$a), "cvt.rn.f64.u8\t$d, $a", - [(set RegF64:$d, (uint_to_fp RegI8:$a))]>; - def CVT_f64_u16 : InstPTX<(outs RegF64:$d), (ins RegI16:$a), "cvt.rn.f64.u16\t$d, $a", [(set RegF64:$d, (uint_to_fp RegI16:$a))]>; @@ -1144,8 +1075,6 @@ let isReturn = 1, isTerminator = 1, isBarrier = 1 in { ///===- Spill Instructions ------------------------------------------------===// // Special instructions used for stack spilling -def STACKSTOREI8 : InstPTX<(outs), (ins i32imm:$d, RegI8:$a), - "mov.u8\ts$d, $a", []>; def STACKSTOREI16 : InstPTX<(outs), (ins i32imm:$d, RegI16:$a), "mov.u16\ts$d, $a", []>; def STACKSTOREI32 : InstPTX<(outs), (ins i32imm:$d, RegI32:$a), @@ -1157,8 +1086,6 @@ def STACKSTOREF32 : InstPTX<(outs), (ins i32imm:$d, RegF32:$a), def STACKSTOREF64 : InstPTX<(outs), (ins i32imm:$d, RegF64:$a), "mov.f64\ts$d, $a", []>; -def STACKLOADI8 : InstPTX<(outs), (ins RegI8:$d, i32imm:$a), - "mov.u8\t$d, s$a", []>; def STACKLOADI16 : InstPTX<(outs), (ins RegI16:$d, i32imm:$a), "mov.u16\t$d, s$a", []>; def STACKLOADI32 : InstPTX<(outs), (ins RegI32:$d, i32imm:$a), diff --git a/lib/Target/PTX/PTXRegisterInfo.td b/lib/Target/PTX/PTXRegisterInfo.td index 3e7fe56..1313d24 100644 --- a/lib/Target/PTX/PTXRegisterInfo.td +++ b/lib/Target/PTX/PTXRegisterInfo.td @@ -151,137 +151,6 @@ def P125 : PTXReg<"p125">; def P126 : PTXReg<"p126">; def P127 : PTXReg<"p127">; -///===- 8-Bit Registers --------------------------------------------------===// - -def RQ0 : PTXReg<"rq0">; -def RQ1 : PTXReg<"rq1">; -def RQ2 : PTXReg<"rq2">; -def RQ3 : PTXReg<"rq3">; -def RQ4 : PTXReg<"rq4">; -def RQ5 : PTXReg<"rq5">; -def RQ6 : PTXReg<"rq6">; -def RQ7 : PTXReg<"rq7">; -def RQ8 : PTXReg<"rq8">; -def RQ9 : PTXReg<"rq9">; -def RQ10 : PTXReg<"rq10">; -def RQ11 : PTXReg<"rq11">; -def RQ12 : PTXReg<"rq12">; -def RQ13 : PTXReg<"rq13">; -def RQ14 : PTXReg<"rq14">; -def RQ15 : PTXReg<"rq15">; -def RQ16 : PTXReg<"rq16">; -def RQ17 : PTXReg<"rq17">; -def RQ18 : PTXReg<"rq18">; -def RQ19 : PTXReg<"rq19">; -def RQ20 : PTXReg<"rq20">; -def RQ21 : PTXReg<"rq21">; -def RQ22 : PTXReg<"rq22">; -def RQ23 : PTXReg<"rq23">; -def RQ24 : PTXReg<"rq24">; -def RQ25 : PTXReg<"rq25">; -def RQ26 : PTXReg<"rq26">; -def RQ27 : PTXReg<"rq27">; -def RQ28 : PTXReg<"rq28">; -def RQ29 : PTXReg<"rq29">; -def RQ30 : PTXReg<"rq30">; -def RQ31 : PTXReg<"rq31">; -def RQ32 : PTXReg<"rq32">; -def RQ33 : PTXReg<"rq33">; -def RQ34 : PTXReg<"rq34">; -def RQ35 : PTXReg<"rq35">; -def RQ36 : PTXReg<"rq36">; -def RQ37 : PTXReg<"rq37">; -def RQ38 : PTXReg<"rq38">; -def RQ39 : PTXReg<"rq39">; -def RQ40 : PTXReg<"rq40">; -def RQ41 : PTXReg<"rq41">; -def RQ42 : PTXReg<"rq42">; -def RQ43 : PTXReg<"rq43">; -def RQ44 : PTXReg<"rq44">; -def RQ45 : PTXReg<"rq45">; -def RQ46 : PTXReg<"rq46">; -def RQ47 : PTXReg<"rq47">; -def RQ48 : PTXReg<"rq48">; -def RQ49 : PTXReg<"rq49">; -def RQ50 : PTXReg<"rq50">; -def RQ51 : PTXReg<"rq51">; -def RQ52 : PTXReg<"rq52">; -def RQ53 : PTXReg<"rq53">; -def RQ54 : PTXReg<"rq54">; -def RQ55 : PTXReg<"rq55">; -def RQ56 : PTXReg<"rq56">; -def RQ57 : PTXReg<"rq57">; -def RQ58 : PTXReg<"rq58">; -def RQ59 : PTXReg<"rq59">; -def RQ60 : PTXReg<"rq60">; -def RQ61 : PTXReg<"rq61">; -def RQ62 : PTXReg<"rq62">; -def RQ63 : PTXReg<"rq63">; -def RQ64 : PTXReg<"rq64">; -def RQ65 : PTXReg<"rq65">; -def RQ66 : PTXReg<"rq66">; -def RQ67 : PTXReg<"rq67">; -def RQ68 : PTXReg<"rq68">; -def RQ69 : PTXReg<"rq69">; -def RQ70 : PTXReg<"rq70">; -def RQ71 : PTXReg<"rq71">; -def RQ72 : PTXReg<"rq72">; -def RQ73 : PTXReg<"rq73">; -def RQ74 : PTXReg<"rq74">; -def RQ75 : PTXReg<"rq75">; -def RQ76 : PTXReg<"rq76">; -def RQ77 : PTXReg<"rq77">; -def RQ78 : PTXReg<"rq78">; -def RQ79 : PTXReg<"rq79">; -def RQ80 : PTXReg<"rq80">; -def RQ81 : PTXReg<"rq81">; -def RQ82 : PTXReg<"rq82">; -def RQ83 : PTXReg<"rq83">; -def RQ84 : PTXReg<"rq84">; -def RQ85 : PTXReg<"rq85">; -def RQ86 : PTXReg<"rq86">; -def RQ87 : PTXReg<"rq87">; -def RQ88 : PTXReg<"rq88">; -def RQ89 : PTXReg<"rq89">; -def RQ90 : PTXReg<"rq90">; -def RQ91 : PTXReg<"rq91">; -def RQ92 : PTXReg<"rq92">; -def RQ93 : PTXReg<"rq93">; -def RQ94 : PTXReg<"rq94">; -def RQ95 : PTXReg<"rq95">; -def RQ96 : PTXReg<"rq96">; -def RQ97 : PTXReg<"rq97">; -def RQ98 : PTXReg<"rq98">; -def RQ99 : PTXReg<"rq99">; -def RQ100 : PTXReg<"rq100">; -def RQ101 : PTXReg<"rq101">; -def RQ102 : PTXReg<"rq102">; -def RQ103 : PTXReg<"rq103">; -def RQ104 : PTXReg<"rq104">; -def RQ105 : PTXReg<"rq105">; -def RQ106 : PTXReg<"rq106">; -def RQ107 : PTXReg<"rq107">; -def RQ108 : PTXReg<"rq108">; -def RQ109 : PTXReg<"rq109">; -def RQ110 : PTXReg<"rq110">; -def RQ111 : PTXReg<"rq111">; -def RQ112 : PTXReg<"rq112">; -def RQ113 : PTXReg<"rq113">; -def RQ114 : PTXReg<"rq114">; -def RQ115 : PTXReg<"rq115">; -def RQ116 : PTXReg<"rq116">; -def RQ117 : PTXReg<"rq117">; -def RQ118 : PTXReg<"rq118">; -def RQ119 : PTXReg<"rq119">; -def RQ120 : PTXReg<"rq120">; -def RQ121 : PTXReg<"rq121">; -def RQ122 : PTXReg<"rq122">; -def RQ123 : PTXReg<"rq123">; -def RQ124 : PTXReg<"rq124">; -def RQ125 : PTXReg<"rq125">; -def RQ126 : PTXReg<"rq126">; -def RQ127 : PTXReg<"rq127">; - ///===- 16-Bit Registers --------------------------------------------------===// def RH0 : PTXReg<"rh0">; @@ -679,7 +548,6 @@ def RD127 : PTXReg<"rd127">; // Register classes //===----------------------------------------------------------------------===// def RegPred : RegisterClass<"PTX", [i1], 8, (sequence "P%u", 0, 127)>; -def RegI8 : RegisterClass<"PTX", [i8], 8, (sequence "RQ%u", 0, 127)>; def RegI16 : RegisterClass<"PTX", [i16], 16, (sequence "RH%u", 0, 127)>; def RegI32 : RegisterClass<"PTX", [i32], 32, (sequence "R%u", 0, 127)>; def RegI64 : RegisterClass<"PTX", [i64], 64, (sequence "RD%u", 0, 127)>; diff --git a/lib/Target/PTX/generate-register-td.py b/lib/Target/PTX/generate-register-td.py index 2402391..1528690 100755 --- a/lib/Target/PTX/generate-register-td.py +++ b/lib/Target/PTX/generate-register-td.py @@ -15,16 +15,15 @@ from sys import argv, exit, stdout -if len(argv) != 6: - print('Usage: generate-register-td.py ') +if len(argv) != 5: + print('Usage: generate-register-td.py ') exit(1) try: num_pred = int(argv[1]) - num_8bit = int(argv[2]) - num_16bit = int(argv[3]) - num_32bit = int(argv[4]) - num_64bit = int(argv[5]) + num_16bit = int(argv[2]) + num_32bit = int(argv[3]) + num_64bit = int(argv[4]) except: print('ERROR: Invalid integer parameter') exit(1) @@ -61,11 +60,6 @@ td_file.write('\n///===- Predicate Registers ----------------------------------- for r in range(0, num_pred): td_file.write('def P%d : PTXReg<"p%d">;\n' % (r, r)) -# Print 8-bit registers -td_file.write('\n///===- 8-Bit Registers --------------------------------------------------===//\n\n') -for r in range(0, num_8bit): - td_file.write('def RQ%d : PTXReg<"rq%d">;\n' % (r, r)) - # Print 16-bit registers td_file.write('\n///===- 16-Bit Registers --------------------------------------------------===//\n\n') for r in range(0, num_16bit): @@ -92,7 +86,6 @@ td_file.write(''' # Print register classes td_file.write('def RegPred : RegisterClass<"PTX", [i1], 8, (sequence "P%%u", 0, %d)>;\n' % (num_pred-1)) -td_file.write('def RegI8 : RegisterClass<"PTX", [i8], 8, (sequence "RQ%%u", 0, %d)>;\n' % (num_8bit-1)) td_file.write('def RegI16 : RegisterClass<"PTX", [i16], 16, (sequence "RH%%u", 0, %d)>;\n' % (num_16bit-1)) td_file.write('def RegI32 : RegisterClass<"PTX", [i32], 32, (sequence "R%%u", 0, %d)>;\n' % (num_32bit-1)) td_file.write('def RegI64 : RegisterClass<"PTX", [i64], 64, (sequence "RD%%u", 0, %d)>;\n' % (num_64bit-1)) @@ -108,20 +101,16 @@ td_file = open('PTXCallingConv.td', 'w') # Reserve 10% of the available registers for return values, and the other 90% # for parameters num_ret_pred = int(0.1 * num_pred) -num_ret_8bit = int(0.1 * num_8bit) num_ret_16bit = int(0.1 * num_16bit) num_ret_32bit = int(0.1 * num_32bit) num_ret_64bit = int(0.1 * num_64bit) num_param_pred = num_pred - num_ret_pred -num_param_8bit = num_8bit - num_ret_8bit num_param_16bit = num_16bit - num_ret_16bit num_param_32bit = num_32bit - num_ret_32bit num_param_64bit = num_64bit - num_ret_64bit param_regs_pred = [('P%d' % (i+num_ret_pred)) for i in range(0, num_param_pred)] ret_regs_pred = ['P%d' % i for i in range(0, num_ret_pred)] -param_regs_8bit = [('RQ%d' % (i+num_ret_8bit)) for i in range(0, num_param_8bit)] -ret_regs_8bit = ['RQ%d' % i for i in range(0, num_ret_8bit)] param_regs_16bit = [('RH%d' % (i+num_ret_16bit)) for i in range(0, num_param_16bit)] ret_regs_16bit = ['RH%d' % i for i in range(0, num_ret_16bit)] param_regs_32bit = [('R%d' % (i+num_ret_32bit)) for i in range(0, num_param_32bit)] @@ -131,8 +120,6 @@ ret_regs_64bit = ['RD%d' % i for i in range(0, num_ret_64bit)] param_list_pred = reduce(lambda x, y: '%s, %s' % (x, y), param_regs_pred) ret_list_pred = reduce(lambda x, y: '%s, %s' % (x, y), ret_regs_pred) -param_list_8bit = reduce(lambda x, y: '%s, %s' % (x, y), param_regs_8bit) -ret_list_8bit = reduce(lambda x, y: '%s, %s' % (x, y), ret_regs_8bit) param_list_16bit = reduce(lambda x, y: '%s, %s' % (x, y), param_regs_16bit) ret_list_16bit = reduce(lambda x, y: '%s, %s' % (x, y), ret_regs_16bit) param_list_32bit = reduce(lambda x, y: '%s, %s' % (x, y), param_regs_32bit) @@ -157,7 +144,6 @@ td_file.write(''' // PTX Formal Parameter Calling Convention def CC_PTX : CallingConv<[ CCIfType<[i1], CCAssignToReg<[%s]>>, - CCIfType<[i8], CCAssignToReg<[%s]>>, CCIfType<[i16], CCAssignToReg<[%s]>>, CCIfType<[i32,f32], CCAssignToReg<[%s]>>, CCIfType<[i64,f64], CCAssignToReg<[%s]>> @@ -166,13 +152,12 @@ def CC_PTX : CallingConv<[ // PTX Return Value Calling Convention def RetCC_PTX : CallingConv<[ CCIfType<[i1], CCAssignToReg<[%s]>>, - CCIfType<[i8], CCAssignToReg<[%s]>>, CCIfType<[i16], CCAssignToReg<[%s]>>, CCIfType<[i32,f32], CCAssignToReg<[%s]>>, CCIfType<[i64,f64], CCAssignToReg<[%s]>> ]>; -''' % (param_list_pred, param_list_8bit, param_list_16bit, param_list_32bit, param_list_64bit, - ret_list_pred, ret_list_8bit, ret_list_16bit, ret_list_32bit, ret_list_64bit)) +''' % (param_list_pred, param_list_16bit, param_list_32bit, param_list_64bit, + ret_list_pred, ret_list_16bit, ret_list_32bit, ret_list_64bit)) td_file.close() diff --git a/test/CodeGen/PTX/cvt.ll b/test/CodeGen/PTX/cvt.ll index dbabbf8..18f7ef3 100644 --- a/test/CodeGen/PTX/cvt.ll +++ b/test/CodeGen/PTX/cvt.ll @@ -3,17 +3,6 @@ ; preds ; (note: we convert back to i32 to return) -define ptx_device i32 @cvt_pred_i8(i8 %x, i1 %y) { -; CHECK: setp.gt.b8 p[[P0:[0-9]+]], rq{{[0-9]+}}, 0 -; CHECK-NEXT: and.pred p0, p[[P0:[0-9]+]], p{{[0-9]+}}; -; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0:[0-9]+]]; -; CHECK-NEXT: ret; - %a = trunc i8 %x to i1 - %b = and i1 %a, %y - %c = zext i1 %b to i32 - ret i32 %c -} - define ptx_device i32 @cvt_pred_i16(i16 %x, i1 %y) { ; CHECK: setp.gt.b16 p[[P0:[0-9]+]], rh{{[0-9]+}}, 0 ; CHECK-NEXT: and.pred p0, p[[P0:[0-9]+]], p{{[0-9]+}}; @@ -69,43 +58,6 @@ define ptx_device i32 @cvt_pred_f64(double %x, i1 %y) { ret i32 %c } -; i8 - -define ptx_device i8 @cvt_i8_preds(i1 %x) { -; CHECK: selp.u8 rq{{[0-9]+}}, 1, 0, p{{[0-9]+}}; -; CHECK-NEXT: ret; - %a = zext i1 %x to i8 - ret i8 %a -} - -define ptx_device i8 @cvt_i8_i32(i32 %x) { -; CHECK: cvt.u8.u32 rq{{[0-9]+}}, r{{[0-9]+}}; -; CHECK-NEXT: ret; - %a = trunc i32 %x to i8 - ret i8 %a -} - -define ptx_device i8 @cvt_i8_i64(i64 %x) { -; CHECK: cvt.u8.u64 rq{{[0-9]+}}, rd{{[0-9]+}}; -; CHECK-NEXT: ret; - %a = trunc i64 %x to i8 - ret i8 %a -} - -define ptx_device i8 @cvt_i8_f32(float %x) { -; CHECK: cvt.rzi.u8.f32 rq{{[0-9]+}}, r{{[0-9]+}}; -; CHECK-NEXT: ret; - %a = fptoui float %x to i8 - ret i8 %a -} - -define ptx_device i8 @cvt_i8_f64(double %x) { -; CHECK: cvt.rzi.u8.f64 rq{{[0-9]+}}, rd{{[0-9]+}}; -; CHECK-NEXT: ret; - %a = fptoui double %x to i8 - ret i8 %a -} - ; i16 define ptx_device i16 @cvt_i16_preds(i1 %x) { @@ -115,13 +67,6 @@ define ptx_device i16 @cvt_i16_preds(i1 %x) { ret i16 %a } -define ptx_device i16 @cvt_i16_i8(i8 %x) { -; CHECK: cvt.u16.u8 rh{{[0-9]+}}, rq{{[0-9]+}}; -; CHECK-NEXT: ret; - %a = zext i8 %x to i16 - ret i16 %a -} - define ptx_device i16 @cvt_i16_i32(i32 %x) { ; CHECK: cvt.u16.u32 rh{{[0-9]+}}, r{{[0-9]+}}; ; CHECK-NEXT: ret; @@ -159,13 +104,6 @@ define ptx_device i32 @cvt_i32_preds(i1 %x) { ret i32 %a } -define ptx_device i32 @cvt_i32_i8(i8 %x) { -; CHECK: cvt.u32.u8 r{{[0-9]+}}, rq{{[0-9]+}}; -; CHECK-NEXT: ret; - %a = zext i8 %x to i32 - ret i32 %a -} - define ptx_device i32 @cvt_i32_i16(i16 %x) { ; CHECK: cvt.u32.u16 r{{[0-9]+}}, rh{{[0-9]+}}; ; CHECK-NEXT: ret; @@ -203,13 +141,6 @@ define ptx_device i64 @cvt_i64_preds(i1 %x) { ret i64 %a } -define ptx_device i64 @cvt_i64_i8(i8 %x) { -; CHECK: cvt.u64.u8 rd{{[0-9]+}}, rq{{[0-9]+}}; -; CHECK-NEXT: ret; - %a = zext i8 %x to i64 - ret i64 %a -} - define ptx_device i64 @cvt_i64_i16(i16 %x) { ; CHECK: cvt.u64.u16 rd{{[0-9]+}}, rh{{[0-9]+}}; ; CHECK-NEXT: ret; @@ -247,13 +178,6 @@ define ptx_device float @cvt_f32_preds(i1 %x) { ret float %a } -define ptx_device float @cvt_f32_i8(i8 %x) { -; CHECK: cvt.rn.f32.u8 r{{[0-9]+}}, rq{{[0-9]+}}; -; CHECK-NEXT: ret; - %a = uitofp i8 %x to float - ret float %a -} - define ptx_device float @cvt_f32_i16(i16 %x) { ; CHECK: cvt.rn.f32.u16 r{{[0-9]+}}, rh{{[0-9]+}}; ; CHECK-NEXT: ret; @@ -291,13 +215,6 @@ define ptx_device double @cvt_f64_preds(i1 %x) { ret double %a } -define ptx_device double @cvt_f64_i8(i8 %x) { -; CHECK: cvt.rn.f64.u8 rd{{[0-9]+}}, rq{{[0-9]+}}; -; CHECK-NEXT: ret; - %a = uitofp i8 %x to double - ret double %a -} - define ptx_device double @cvt_f64_i16(i16 %x) { ; CHECK: cvt.rn.f64.u16 rd{{[0-9]+}}, rh{{[0-9]+}}; ; CHECK-NEXT: ret; diff --git a/test/CodeGen/PTX/ld.ll b/test/CodeGen/PTX/ld.ll index 951b14b..d184d12 100644 --- a/test/CodeGen/PTX/ld.ll +++ b/test/CodeGen/PTX/ld.ll @@ -1,17 +1,5 @@ ; RUN: llc < %s -march=ptx32 | FileCheck %s -;CHECK: .extern .global .b8 array_i8[10]; -@array_i8 = external global [10 x i8] - -;CHECK: .extern .const .b8 array_constant_i8[10]; -@array_constant_i8 = external addrspace(1) constant [10 x i8] - -;CHECK: .extern .local .b8 array_local_i8[10]; -@array_local_i8 = external addrspace(2) global [10 x i8] - -;CHECK: .extern .shared .b8 array_shared_i8[10]; -@array_shared_i8 = external addrspace(4) global [10 x i8] - ;CHECK: .extern .global .b8 array_i16[20]; @array_i16 = external global [10 x i16] @@ -72,13 +60,6 @@ ;CHECK: .extern .shared .b8 array_shared_double[80]; @array_shared_double = external addrspace(4) global [10 x double] -define ptx_device i8 @t1_u8(i8* %p) { -entry: -;CHECK: ld.global.u8 rq{{[0-9]+}}, [r{{[0-9]+}}]; -;CHECK-NEXT: ret; - %x = load i8* %p - ret i8 %x -} define ptx_device i16 @t1_u16(i16* %p) { entry: @@ -120,15 +101,6 @@ entry: ret double %x } -define ptx_device i8 @t2_u8(i8* %p) { -entry: -;CHECK: ld.global.u8 rq{{[0-9]+}}, [r{{[0-9]+}}+1]; -;CHECK-NEXT: ret; - %i = getelementptr i8* %p, i32 1 - %x = load i8* %i - ret i8 %x -} - define ptx_device i16 @t2_u16(i16* %p) { entry: ;CHECK: ld.global.u16 rh{{[0-9]+}}, [r{{[0-9]+}}+2]; @@ -174,15 +146,6 @@ entry: ret double %x } -define ptx_device i8 @t3_u8(i8* %p, i32 %q) { -entry: -;CHECK: add.u32 r[[R0:[0-9]+]], r{{[0-9]+}}, r{{[0-9]+}}; -;CHECK-NEXT: ld.global.u8 rq{{[0-9]+}}, [r[[R0]]]; - %i = getelementptr i8* %p, i32 %q - %x = load i8* %i - ret i8 %x -} - define ptx_device i16 @t3_u16(i16* %p, i32 %q) { entry: ;CHECK: shl.b32 r[[R0:[0-9]+]], r{{[0-9]+}}, 1; @@ -233,16 +196,6 @@ entry: ret double %x } -define ptx_device i8 @t4_global_u8() { -entry: -;CHECK: mov.u32 r[[R0:[0-9]+]], array_i8; -;CHECK-NEXT: ld.global.u8 rq{{[0-9]+}}, [r[[R0]]]; -;CHECK-NEXT: ret; - %i = getelementptr [10 x i8]* @array_i8, i32 0, i32 0 - %x = load i8* %i - ret i8 %x -} - define ptx_device i16 @t4_global_u16() { entry: ;CHECK: mov.u32 r[[R0:[0-9]+]], array_i16; @@ -343,16 +296,6 @@ entry: ret double %x } -define ptx_device i8 @t4_local_u8() { -entry: -;CHECK: mov.u32 r[[R0:[0-9]+]], array_local_i8; -;CHECK-NEXT: ld.local.u8 rq{{[0-9]+}}, [r[[R0]]]; -;CHECK-NEXT: ret; - %i = getelementptr [10 x i8] addrspace(2)* @array_local_i8, i32 0, i32 0 - %x = load i8 addrspace(2)* %i - ret i8 %x -} - define ptx_device i16 @t4_local_u16() { entry: ;CHECK: mov.u32 r[[R0:[0-9]+]], array_local_i16; @@ -403,16 +346,6 @@ entry: ret double %x } -define ptx_device i8 @t4_shared_u8() { -entry: -;CHECK: mov.u32 r[[R0:[0-9]+]], array_shared_i8; -;CHECK-NEXT: ld.shared.u8 rq{{[0-9]+}}, [r[[R0]]]; -;CHECK-NEXT: ret; - %i = getelementptr [10 x i8] addrspace(4)* @array_shared_i8, i32 0, i32 0 - %x = load i8 addrspace(4)* %i - ret i8 %x -} - define ptx_device i16 @t4_shared_u16() { entry: ;CHECK: mov.u32 r[[R0:[0-9]+]], array_shared_i16; @@ -463,16 +396,6 @@ entry: ret double %x } -define ptx_device i8 @t5_u8() { -entry: -;CHECK: mov.u32 r[[R0:[0-9]+]], array_i8; -;CHECK-NEXT: ld.global.u8 rq{{[0-9]+}}, [r[[R0]]+1]; -;CHECK-NEXT: ret; - %i = getelementptr [10 x i8]* @array_i8, i32 0, i32 1 - %x = load i8* %i - ret i8 %x -} - define ptx_device i16 @t5_u16() { entry: ;CHECK: mov.u32 r[[R0:[0-9]+]], array_i16; diff --git a/test/CodeGen/PTX/mov.ll b/test/CodeGen/PTX/mov.ll index b930b4c..cce6a5b 100644 --- a/test/CodeGen/PTX/mov.ll +++ b/test/CodeGen/PTX/mov.ll @@ -1,11 +1,5 @@ ; RUN: llc < %s -march=ptx32 | FileCheck %s -define ptx_device i8 @t1_u8() { -; CHECK: mov.u8 rq{{[0-9]+}}, 0; -; CHECK: ret; - ret i8 0 -} - define ptx_device i16 @t1_u16() { ; CHECK: mov.u16 rh{{[0-9]+}}, 0; ; CHECK: ret; @@ -36,12 +30,6 @@ define ptx_device double @t1_f64() { ret double 0.0 } -define ptx_device i8 @t2_u8(i8 %x) { -; CHECK: mov.u8 rq{{[0-9]+}}, rq{{[0-9]+}}; -; CHECK: ret; - ret i8 %x -} - define ptx_device i16 @t2_u16(i16 %x) { ; CHECK: mov.u16 rh{{[0-9]+}}, rh{{[0-9]+}}; ; CHECK: ret; diff --git a/test/CodeGen/PTX/st.ll b/test/CodeGen/PTX/st.ll index 596d189..b08528e 100644 --- a/test/CodeGen/PTX/st.ll +++ b/test/CodeGen/PTX/st.ll @@ -1,17 +1,5 @@ ; RUN: llc < %s -march=ptx32 | FileCheck %s -;CHECK: .extern .global .b8 array_i8[10]; -@array_i8 = external global [10 x i8] - -;CHECK: .extern .const .b8 array_constant_i8[10]; -@array_constant_i8 = external addrspace(1) constant [10 x i8] - -;CHECK: .extern .local .b8 array_local_i8[10]; -@array_local_i8 = external addrspace(2) global [10 x i8] - -;CHECK: .extern .shared .b8 array_shared_i8[10]; -@array_shared_i8 = external addrspace(4) global [10 x i8] - ;CHECK: .extern .global .b8 array_i16[20]; @array_i16 = external global [10 x i16] @@ -72,13 +60,6 @@ ;CHECK: .extern .shared .b8 array_shared_double[80]; @array_shared_double = external addrspace(4) global [10 x double] -define ptx_device void @t1_u8(i8* %p, i8 %x) { -entry: -;CHECK: st.global.u8 [r{{[0-9]+}}], rq{{[0-9]+}}; -;CHECK-NEXT: ret; - store i8 %x, i8* %p - ret void -} define ptx_device void @t1_u16(i16* %p, i16 %x) { entry: @@ -120,15 +101,6 @@ entry: ret void } -define ptx_device void @t2_u8(i8* %p, i8 %x) { -entry: -;CHECK: st.global.u8 [r{{[0-9]+}}+1], rq{{[0-9]+}}; -;CHECK-NEXT: ret; - %i = getelementptr i8* %p, i32 1 - store i8 %x, i8* %i - ret void -} - define ptx_device void @t2_u16(i16* %p, i16 %x) { entry: ;CHECK: st.global.u16 [r{{[0-9]+}}+2], rh{{[0-9]+}}; @@ -174,16 +146,6 @@ entry: ret void } -define ptx_device void @t3_u8(i8* %p, i32 %q, i8 %x) { -entry: -;CHECK: add.u32 r[[R0:[0-9]+]], r{{[0-9]+}}, r{{[0-9]+}}; -;CHECK-NEXT: st.global.u8 [r[[R0]]], rq{{[0-9]+}}; -;CHECK-NEXT: ret; - %i = getelementptr i8* %p, i32 %q - store i8 %x, i8* %i - ret void -} - define ptx_device void @t3_u16(i16* %p, i32 %q, i16 %x) { entry: ;CHECK: shl.b32 r[[R0:[0-9]+]], r{{[0-9]+}}, 1; @@ -239,16 +201,6 @@ entry: ret void } -define ptx_device void @t4_global_u8(i8 %x) { -entry: -;CHECK: mov.u32 r[[R0:[0-9]+]], array_i8; -;CHECK-NEXT: st.global.u8 [r[[R0]]], rq{{[0-9]+}}; -;CHECK-NEXT: ret; - %i = getelementptr [10 x i8]* @array_i8, i8 0, i8 0 - store i8 %x, i8* %i - ret void -} - define ptx_device void @t4_global_u16(i16 %x) { entry: ;CHECK: mov.u32 r[[R0:[0-9]+]], array_i16; @@ -299,16 +251,6 @@ entry: ret void } -define ptx_device void @t4_local_u8(i8 %x) { -entry: -;CHECK: mov.u32 r[[R0:[0-9]+]], array_local_i8; -;CHECK-NEXT: st.local.u8 [r[[R0]]], rq{{[0-9]+}}; -;CHECK-NEXT: ret; - %i = getelementptr [10 x i8] addrspace(2)* @array_local_i8, i32 0, i32 0 - store i8 %x, i8 addrspace(2)* %i - ret void -} - define ptx_device void @t4_local_u16(i16 %x) { entry: ;CHECK: mov.u32 r[[R0:[0-9]+]], array_local_i16; @@ -359,16 +301,6 @@ entry: ret void } -define ptx_device void @t4_shared_u8(i8 %x) { -entry: -;CHECK: mov.u32 r[[R0:[0-9]+]], array_shared_i8; -;CHECK-NEXT: st.shared.u8 [r[[R0]]], rq{{[0-9]+}}; -;CHECK-NEXT: ret; - %i = getelementptr [10 x i8] addrspace(4)* @array_shared_i8, i32 0, i32 0 - store i8 %x, i8 addrspace(4)* %i - ret void -} - define ptx_device void @t4_shared_u16(i16 %x) { entry: ;CHECK: mov.u32 r[[R0:[0-9]+]], array_shared_i16; @@ -419,16 +351,6 @@ entry: ret void } -define ptx_device void @t5_u8(i8 %x) { -entry: -;CHECK: mov.u32 r[[R0:[0-9]+]], array_i8; -;CHECK-NEXT: st.global.u8 [r[[R0]]+1], rq{{[0-9]+}}; -;CHECK-NEXT: ret; - %i = getelementptr [10 x i8]* @array_i8, i32 0, i32 1 - store i8 %x, i8* %i - ret void -} - define ptx_device void @t5_u16(i16 %x) { entry: ;CHECK: mov.u32 r[[R0:[0-9]+]], array_i16; -- cgit v1.1 From 14d71aac84505fb69b28436a02465df73ea6c6f5 Mon Sep 17 00:00:00 2001 From: Chad Rosier Date: Sat, 25 Jun 2011 18:51:28 +0000 Subject: Replace dyn_cast<> with cast<> since the cast is already guarded by the necessary check. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133874 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86ISelLowering.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index bab15e6..0810267 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -2506,7 +2506,7 @@ bool MatchingStackOffset(SDValue Arg, unsigned Offset, ISD::ArgFlagsTy Flags, return false; FI = FINode->getIndex(); } else if (Arg.getOpcode() == ISD::FrameIndex && Flags.isByVal()) { - FrameIndexSDNode *FINode = dyn_cast(Arg); + FrameIndexSDNode *FINode = cast(Arg); FI = FINode->getIndex(); Bytes = Flags.getByValSize(); } else -- cgit v1.1 From 0b19acbb8f86edeec16a43450b983769188b9de3 Mon Sep 17 00:00:00 2001 From: Dan Bailey Date: Sat, 25 Jun 2011 19:41:17 +0000 Subject: PTX: corrected tests that were failing git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133875 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/CodeGen/PTX/cvt.ll | 10 +++++----- test/CodeGen/PTX/setp.ll | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/test/CodeGen/PTX/cvt.ll b/test/CodeGen/PTX/cvt.ll index 18f7ef3..853abaf 100644 --- a/test/CodeGen/PTX/cvt.ll +++ b/test/CodeGen/PTX/cvt.ll @@ -4,7 +4,7 @@ ; (note: we convert back to i32 to return) define ptx_device i32 @cvt_pred_i16(i16 %x, i1 %y) { -; CHECK: setp.gt.b16 p[[P0:[0-9]+]], rh{{[0-9]+}}, 0 +; CHECK: setp.gt.u16 p[[P0:[0-9]+]], rh{{[0-9]+}}, 0 ; CHECK-NEXT: and.pred p0, p[[P0:[0-9]+]], p{{[0-9]+}}; ; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0:[0-9]+]]; ; CHECK-NEXT: ret; @@ -15,7 +15,7 @@ define ptx_device i32 @cvt_pred_i16(i16 %x, i1 %y) { } define ptx_device i32 @cvt_pred_i32(i32 %x, i1 %y) { -; CHECK: setp.gt.b32 p[[P0:[0-9]+]], r{{[0-9]+}}, 0 +; CHECK: setp.gt.u32 p[[P0:[0-9]+]], r{{[0-9]+}}, 0 ; CHECK-NEXT: and.pred p0, p[[P0:[0-9]+]], p{{[0-9]+}}; ; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0:[0-9]+]]; ; CHECK-NEXT: ret; @@ -26,7 +26,7 @@ define ptx_device i32 @cvt_pred_i32(i32 %x, i1 %y) { } define ptx_device i32 @cvt_pred_i64(i64 %x, i1 %y) { -; CHECK: setp.gt.b64 p[[P0:[0-9]+]], rd{{[0-9]+}}, 0 +; CHECK: setp.gt.u64 p[[P0:[0-9]+]], rd{{[0-9]+}}, 0 ; CHECK-NEXT: and.pred p0, p[[P0:[0-9]+]], p{{[0-9]+}}; ; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0:[0-9]+]]; ; CHECK-NEXT: ret; @@ -37,7 +37,7 @@ define ptx_device i32 @cvt_pred_i64(i64 %x, i1 %y) { } define ptx_device i32 @cvt_pred_f32(float %x, i1 %y) { -; CHECK: setp.gt.b32 p[[P0:[0-9]+]], r{{[0-9]+}}, 0 +; CHECK: setp.gt.f32 p[[P0:[0-9]+]], r{{[0-9]+}}, 0 ; CHECK-NEXT: and.pred p0, p[[P0:[0-9]+]], p{{[0-9]+}}; ; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0:[0-9]+]]; ; CHECK-NEXT: ret; @@ -48,7 +48,7 @@ define ptx_device i32 @cvt_pred_f32(float %x, i1 %y) { } define ptx_device i32 @cvt_pred_f64(double %x, i1 %y) { -; CHECK: setp.gt.b64 p[[P0:[0-9]+]], rd{{[0-9]+}}, 0 +; CHECK: setp.gt.f64 p[[P0:[0-9]+]], rd{{[0-9]+}}, 0 ; CHECK-NEXT: and.pred p0, p[[P0:[0-9]+]], p{{[0-9]+}}; ; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0:[0-9]+]]; ; CHECK-NEXT: ret; diff --git a/test/CodeGen/PTX/setp.ll b/test/CodeGen/PTX/setp.ll index b8cb364..e0044d6 100644 --- a/test/CodeGen/PTX/setp.ll +++ b/test/CodeGen/PTX/setp.ll @@ -193,7 +193,7 @@ define ptx_device i32 @test_setp_4_op_format_1(i32 %x, i32 %y, i32 %u, i32 %v) { } define ptx_device i32 @test_setp_4_op_format_2(i32 %x, i32 %y, i32 %w) { -; CHECK: setp.gt.b32 p[[P0:[0-9]+]], r{{[0-9]+}}, 0; +; CHECK: setp.gt.u32 p[[P0:[0-9]+]], r{{[0-9]+}}, 0; ; CHECK-NEXT: setp.eq.and.u32 p[[P0]], r{{[0-9]+}}, r{{[0-9]+}}, !p[[P0]]; ; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0]]; ; CHECK-NEXT: ret; -- cgit v1.1 From 79db6a1db623a574eeaef746b08b1eb1d26a6914 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Sun, 26 Jun 2011 19:47:36 +0000 Subject: Remove unnecessary wrapper. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133886 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/SimpleRegisterCoalescing.cpp | 31 +++++++++++++++---------------- lib/CodeGen/SimpleRegisterCoalescing.h | 13 ++----------- 2 files changed, 17 insertions(+), 27 deletions(-) diff --git a/lib/CodeGen/SimpleRegisterCoalescing.cpp b/lib/CodeGen/SimpleRegisterCoalescing.cpp index 221bec5..f58077b 100644 --- a/lib/CodeGen/SimpleRegisterCoalescing.cpp +++ b/lib/CodeGen/SimpleRegisterCoalescing.cpp @@ -839,8 +839,7 @@ SimpleRegisterCoalescing::isWinToJoinCrossClass(unsigned SrcReg, /// if the copy was successfully coalesced away. If it is not currently /// possible to coalesce this interval, but it may be possible if other /// things get coalesced, then it returns true by reference in 'Again'. -bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) { - MachineInstr *CopyMI = TheCopy.MI; +bool SimpleRegisterCoalescing::JoinCopy(MachineInstr *CopyMI, bool &Again) { Again = false; if (JoinedCopies.count(CopyMI) || ReMatCopies.count(CopyMI)) @@ -1268,12 +1267,12 @@ namespace { } void SimpleRegisterCoalescing::CopyCoalesceInMBB(MachineBasicBlock *MBB, - std::vector &TryAgain) { + std::vector &TryAgain) { DEBUG(dbgs() << MBB->getName() << ":\n"); - SmallVector VirtCopies; - SmallVector PhysCopies; - SmallVector ImpDefCopies; + SmallVector VirtCopies; + SmallVector PhysCopies; + SmallVector ImpDefCopies; for (MachineBasicBlock::iterator MII = MBB->begin(), E = MBB->end(); MII != E;) { MachineInstr *Inst = MII++; @@ -1292,32 +1291,32 @@ void SimpleRegisterCoalescing::CopyCoalesceInMBB(MachineBasicBlock *MBB, bool SrcIsPhys = TargetRegisterInfo::isPhysicalRegister(SrcReg); bool DstIsPhys = TargetRegisterInfo::isPhysicalRegister(DstReg); if (li_->hasInterval(SrcReg) && li_->getInterval(SrcReg).empty()) - ImpDefCopies.push_back(CopyRec(Inst, 0)); + ImpDefCopies.push_back(Inst); else if (SrcIsPhys || DstIsPhys) - PhysCopies.push_back(CopyRec(Inst, 0)); + PhysCopies.push_back(Inst); else - VirtCopies.push_back(CopyRec(Inst, 0)); + VirtCopies.push_back(Inst); } // Try coalescing implicit copies and insert_subreg first, // followed by copies to / from physical registers, then finally copies // from virtual registers to virtual registers. for (unsigned i = 0, e = ImpDefCopies.size(); i != e; ++i) { - CopyRec &TheCopy = ImpDefCopies[i]; + MachineInstr *TheCopy = ImpDefCopies[i]; bool Again = false; if (!JoinCopy(TheCopy, Again)) if (Again) TryAgain.push_back(TheCopy); } for (unsigned i = 0, e = PhysCopies.size(); i != e; ++i) { - CopyRec &TheCopy = PhysCopies[i]; + MachineInstr *TheCopy = PhysCopies[i]; bool Again = false; if (!JoinCopy(TheCopy, Again)) if (Again) TryAgain.push_back(TheCopy); } for (unsigned i = 0, e = VirtCopies.size(); i != e; ++i) { - CopyRec &TheCopy = VirtCopies[i]; + MachineInstr *TheCopy = VirtCopies[i]; bool Again = false; if (!JoinCopy(TheCopy, Again)) if (Again) @@ -1328,7 +1327,7 @@ void SimpleRegisterCoalescing::CopyCoalesceInMBB(MachineBasicBlock *MBB, void SimpleRegisterCoalescing::joinIntervals() { DEBUG(dbgs() << "********** JOINING INTERVALS ***********\n"); - std::vector TryAgainList; + std::vector TryAgainList; if (loopInfo->empty()) { // If there are no loops in the function, join intervals in function order. for (MachineFunction::iterator I = mf_->begin(), E = mf_->end(); @@ -1362,14 +1361,14 @@ void SimpleRegisterCoalescing::joinIntervals() { ProgressMade = false; for (unsigned i = 0, e = TryAgainList.size(); i != e; ++i) { - CopyRec &TheCopy = TryAgainList[i]; - if (!TheCopy.MI) + MachineInstr *&TheCopy = TryAgainList[i]; + if (!TheCopy) continue; bool Again = false; bool Success = JoinCopy(TheCopy, Again); if (Success || !Again) { - TheCopy.MI = 0; // Mark this one as done. + TheCopy= 0; // Mark this one as done. ProgressMade = true; } } diff --git a/lib/CodeGen/SimpleRegisterCoalescing.h b/lib/CodeGen/SimpleRegisterCoalescing.h index 92f6c64..5c6738b 100644 --- a/lib/CodeGen/SimpleRegisterCoalescing.h +++ b/lib/CodeGen/SimpleRegisterCoalescing.h @@ -27,15 +27,6 @@ namespace llvm { class VirtRegMap; class MachineLoopInfo; - /// CopyRec - Representation for copy instructions in coalescer queue. - /// - struct CopyRec { - MachineInstr *MI; - unsigned LoopDepth; - CopyRec(MachineInstr *mi, unsigned depth) - : MI(mi), LoopDepth(depth) {} - }; - class SimpleRegisterCoalescing : public MachineFunctionPass, public RegisterCoalescer { MachineFunction* mf_; @@ -88,14 +79,14 @@ namespace llvm { /// CopyCoalesceInMBB - Coalesce copies in the specified MBB, putting /// copies that cannot yet be coalesced into the "TryAgain" list. void CopyCoalesceInMBB(MachineBasicBlock *MBB, - std::vector &TryAgain); + std::vector &TryAgain); /// JoinCopy - Attempt to join intervals corresponding to SrcReg/DstReg, /// which are the src/dst of the copy instruction CopyMI. This returns true /// if the copy was successfully coalesced away. If it is not currently /// possible to coalesce this interval, but it may be possible if other /// things get coalesced, then it returns true by reference in 'Again'. - bool JoinCopy(CopyRec &TheCopy, bool &Again); + bool JoinCopy(MachineInstr *TheCopy, bool &Again); /// JoinIntervals - Attempt to join these two intervals. On failure, this /// returns false. The output "SrcInt" will not have been modified, so we can -- cgit v1.1 From fdf16ca44f130afe80c57481d0c08130aa08cc09 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Sun, 26 Jun 2011 21:41:06 +0000 Subject: Move RegisterCoalescer.h to lib/CodeGen. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133895 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CodeGen/RegisterCoalescer.h | 244 ------------------------------- lib/CodeGen/PreAllocSplitting.cpp | 2 +- lib/CodeGen/RegAllocBasic.cpp | 2 +- lib/CodeGen/RegAllocGreedy.cpp | 2 +- lib/CodeGen/RegAllocLinearScan.cpp | 2 +- lib/CodeGen/RegAllocPBQP.cpp | 2 +- lib/CodeGen/RegisterCoalescer.cpp | 2 +- lib/CodeGen/RegisterCoalescer.h | 244 +++++++++++++++++++++++++++++++ lib/CodeGen/SimpleRegisterCoalescing.cpp | 2 +- lib/CodeGen/SimpleRegisterCoalescing.h | 4 +- 10 files changed, 253 insertions(+), 253 deletions(-) delete mode 100644 include/llvm/CodeGen/RegisterCoalescer.h create mode 100644 lib/CodeGen/RegisterCoalescer.h diff --git a/include/llvm/CodeGen/RegisterCoalescer.h b/include/llvm/CodeGen/RegisterCoalescer.h deleted file mode 100644 index af0b394..0000000 --- a/include/llvm/CodeGen/RegisterCoalescer.h +++ /dev/null @@ -1,244 +0,0 @@ -//===-- RegisterCoalescer.h - Register Coalescing Interface ------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains the abstract interface for register coalescers, -// allowing them to interact with and query register allocators. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Support/IncludeFile.h" -#include "llvm/CodeGen/LiveInterval.h" -#include "llvm/ADT/SmallPtrSet.h" - -#ifndef LLVM_CODEGEN_REGISTER_COALESCER_H -#define LLVM_CODEGEN_REGISTER_COALESCER_H - -namespace llvm { - - class MachineFunction; - class RegallocQuery; - class AnalysisUsage; - class MachineInstr; - class TargetRegisterInfo; - class TargetRegisterClass; - class TargetInstrInfo; - - /// An abstract interface for register coalescers. Coalescers must - /// implement this interface to be part of the coalescer analysis - /// group. - class RegisterCoalescer { - public: - static char ID; // Class identification, replacement for typeinfo - RegisterCoalescer() {} - virtual ~RegisterCoalescer(); // We want to be subclassed - - /// Run the coalescer on this function, providing interference - /// data to query. Return whether we removed any copies. - virtual bool coalesceFunction(MachineFunction &mf, - RegallocQuery &ifd) = 0; - - /// Reset state. Can be used to allow a coalescer run by - /// PassManager to be run again by the register allocator. - virtual void reset(MachineFunction &mf) {} - - /// Register allocators must call this from their own - /// getAnalysisUsage to cover the case where the coalescer is not - /// a Pass in the proper sense and isn't managed by PassManager. - /// PassManager needs to know which analyses to make available and - /// which to invalidate when running the register allocator or any - /// pass that might call coalescing. The long-term solution is to - /// allow hierarchies of PassManagers. - virtual void getAnalysisUsage(AnalysisUsage &AU) const {} - }; - - /// An abstract interface for register allocators to interact with - /// coalescers - /// - /// Example: - /// - /// This is simply an example of how to use the RegallocQuery - /// interface. It is not meant to be used in production. - /// - /// class LinearScanRegallocQuery : public RegallocQuery { - /// private: - /// const LiveIntervals \&li; - /// - /// public: - /// LinearScanRegallocQuery(LiveIntervals &intervals) - /// : li(intervals) {} - /// - /// /// This is pretty slow and conservative, but since linear scan - /// /// allocation doesn't pre-compute interference information it's - /// /// the best we can do. Coalescers are always free to ignore this - /// /// and implement their own discovery strategy. See - /// /// SimpleRegisterCoalescing for an example. - /// void getInterferences(IntervalSet &interferences, - /// const LiveInterval &a) const { - /// for(LiveIntervals::const_iterator iv = li.begin(), - /// ivend = li.end(); - /// iv != ivend; - /// ++iv) { - /// if (interfere(a, iv->second)) { - /// interferences.insert(&iv->second); - /// } - /// } - /// } - /// - /// /// This is *really* slow and stupid. See above. - /// int getNumberOfInterferences(const LiveInterval &a) const { - /// IntervalSet intervals; - /// getInterferences(intervals, a); - /// return intervals.size(); - /// } - /// }; - /// - /// In the allocator: - /// - /// RegisterCoalescer &coalescer = getAnalysis(); - /// - /// // We don't reset the coalescer so if it's already been run this - /// // takes almost no time. - /// LinearScanRegallocQuery ifd(*li_); - /// coalescer.coalesceFunction(fn, ifd); - /// - class RegallocQuery { - public: - typedef SmallPtrSet IntervalSet; - - virtual ~RegallocQuery() {} - - /// Return whether two live ranges interfere. - virtual bool interfere(const LiveInterval &a, - const LiveInterval &b) const { - // A naive test - return a.overlaps(b); - } - - /// Return the set of intervals that interfere with this one. - virtual void getInterferences(IntervalSet &interferences, - const LiveInterval &a) const = 0; - - /// This can often be cheaper than actually returning the - /// interferences. - virtual int getNumberOfInterferences(const LiveInterval &a) const = 0; - - /// Make any data structure updates necessary to reflect - /// coalescing or other modifications. - virtual void updateDataForMerge(const LiveInterval &a, - const LiveInterval &b, - const MachineInstr ©) {} - - /// Allow the register allocator to communicate when it doesn't - /// want a copy coalesced. This may be due to assumptions made by - /// the allocator about various invariants and so this question is - /// a matter of legality, not performance. Performance decisions - /// about which copies to coalesce should be made by the - /// coalescer. - virtual bool isLegalToCoalesce(const MachineInstr &inst) const { - return true; - } - }; - - - /// CoalescerPair - A helper class for register coalescers. When deciding if - /// two registers can be coalesced, CoalescerPair can determine if a copy - /// instruction would become an identity copy after coalescing. - class CoalescerPair { - const TargetInstrInfo &tii_; - const TargetRegisterInfo &tri_; - - /// dstReg_ - The register that will be left after coalescing. It can be a - /// virtual or physical register. - unsigned dstReg_; - - /// srcReg_ - the virtual register that will be coalesced into dstReg. - unsigned srcReg_; - - /// subReg_ - The subregister index of srcReg in dstReg_. It is possible the - /// coalesce srcReg_ into a subreg of the larger dstReg_ when dstReg_ is a - /// virtual register. - unsigned subIdx_; - - /// partial_ - True when the original copy was a partial subregister copy. - bool partial_; - - /// crossClass_ - True when both regs are virtual, and newRC is constrained. - bool crossClass_; - - /// flipped_ - True when DstReg and SrcReg are reversed from the oriignal copy - /// instruction. - bool flipped_; - - /// newRC_ - The register class of the coalesced register, or NULL if dstReg_ - /// is a physreg. - const TargetRegisterClass *newRC_; - - /// compose - Compose subreg indices a and b, either may be 0. - unsigned compose(unsigned, unsigned) const; - - /// isMoveInstr - Return true if MI is a move or subreg instruction. - bool isMoveInstr(const MachineInstr *MI, unsigned &Src, unsigned &Dst, - unsigned &SrcSub, unsigned &DstSub) const; - - public: - CoalescerPair(const TargetInstrInfo &tii, const TargetRegisterInfo &tri) - : tii_(tii), tri_(tri), dstReg_(0), srcReg_(0), subIdx_(0), - partial_(false), crossClass_(false), flipped_(false), newRC_(0) {} - - /// setRegisters - set registers to match the copy instruction MI. Return - /// false if MI is not a coalescable copy instruction. - bool setRegisters(const MachineInstr*); - - /// flip - Swap srcReg_ and dstReg_. Return false if swapping is impossible - /// because dstReg_ is a physical register, or subIdx_ is set. - bool flip(); - - /// isCoalescable - Return true if MI is a copy instruction that will become - /// an identity copy after coalescing. - bool isCoalescable(const MachineInstr*) const; - - /// isPhys - Return true if DstReg is a physical register. - bool isPhys() const { return !newRC_; } - - /// isPartial - Return true if the original copy instruction did not copy the - /// full register, but was a subreg operation. - bool isPartial() const { return partial_; } - - /// isCrossClass - Return true if DstReg is virtual and NewRC is a smaller register class than DstReg's. - bool isCrossClass() const { return crossClass_; } - - /// isFlipped - Return true when getSrcReg is the register being defined by - /// the original copy instruction. - bool isFlipped() const { return flipped_; } - - /// getDstReg - Return the register (virtual or physical) that will remain - /// after coalescing. - unsigned getDstReg() const { return dstReg_; } - - /// getSrcReg - Return the virtual register that will be coalesced away. - unsigned getSrcReg() const { return srcReg_; } - - /// getSubIdx - Return the subregister index in DstReg that SrcReg will be - /// coalesced into, or 0. - unsigned getSubIdx() const { return subIdx_; } - - /// getNewRC - Return the register class of the coalesced register. - const TargetRegisterClass *getNewRC() const { return newRC_; } - }; -} - -// Because of the way .a files work, we must force the SimpleRC -// implementation to be pulled in if the RegisterCoalescing header is -// included. Otherwise we run the risk of RegisterCoalescing being -// used, but the default implementation not being linked into the tool -// that uses it. -FORCE_DEFINING_FILE_TO_BE_LINKED(RegisterCoalescer) -FORCE_DEFINING_FILE_TO_BE_LINKED(SimpleRegisterCoalescing) - -#endif diff --git a/lib/CodeGen/PreAllocSplitting.cpp b/lib/CodeGen/PreAllocSplitting.cpp index d6e31da..26c141d 100644 --- a/lib/CodeGen/PreAllocSplitting.cpp +++ b/lib/CodeGen/PreAllocSplitting.cpp @@ -16,6 +16,7 @@ #define DEBUG_TYPE "pre-alloc-split" #include "VirtRegMap.h" +#include "RegisterCoalescer.h" #include "llvm/CodeGen/CalcSpillWeights.h" #include "llvm/CodeGen/LiveIntervalAnalysis.h" #include "llvm/CodeGen/LiveStackAnalysis.h" @@ -25,7 +26,6 @@ #include "llvm/CodeGen/MachineLoopInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/Passes.h" -#include "llvm/CodeGen/RegisterCoalescer.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" diff --git a/lib/CodeGen/RegAllocBasic.cpp b/lib/CodeGen/RegAllocBasic.cpp index 1d77b29..7961be3 100644 --- a/lib/CodeGen/RegAllocBasic.cpp +++ b/lib/CodeGen/RegAllocBasic.cpp @@ -20,6 +20,7 @@ #include "RenderMachineFunction.h" #include "Spiller.h" #include "VirtRegMap.h" +#include "RegisterCoalescer.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/AliasAnalysis.h" @@ -34,7 +35,6 @@ #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/RegAllocRegistry.h" -#include "llvm/CodeGen/RegisterCoalescer.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegisterInfo.h" diff --git a/lib/CodeGen/RegAllocGreedy.cpp b/lib/CodeGen/RegAllocGreedy.cpp index 8d06325..b2db2de 100644 --- a/lib/CodeGen/RegAllocGreedy.cpp +++ b/lib/CodeGen/RegAllocGreedy.cpp @@ -22,6 +22,7 @@ #include "SpillPlacement.h" #include "SplitKit.h" #include "VirtRegMap.h" +#include "RegisterCoalescer.h" #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Function.h" @@ -37,7 +38,6 @@ #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/RegAllocRegistry.h" -#include "llvm/CodeGen/RegisterCoalescer.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" diff --git a/lib/CodeGen/RegAllocLinearScan.cpp b/lib/CodeGen/RegAllocLinearScan.cpp index 7a2ea6c..dd5a605 100644 --- a/lib/CodeGen/RegAllocLinearScan.cpp +++ b/lib/CodeGen/RegAllocLinearScan.cpp @@ -18,6 +18,7 @@ #include "VirtRegRewriter.h" #include "RegisterClassInfo.h" #include "Spiller.h" +#include "RegisterCoalescer.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Function.h" #include "llvm/CodeGen/CalcSpillWeights.h" @@ -28,7 +29,6 @@ #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/RegAllocRegistry.h" -#include "llvm/CodeGen/RegisterCoalescer.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" diff --git a/lib/CodeGen/RegAllocPBQP.cpp b/lib/CodeGen/RegAllocPBQP.cpp index 49f8fb4..d675841 100644 --- a/lib/CodeGen/RegAllocPBQP.cpp +++ b/lib/CodeGen/RegAllocPBQP.cpp @@ -35,6 +35,7 @@ #include "Splitter.h" #include "VirtRegMap.h" #include "VirtRegRewriter.h" +#include "RegisterCoalescer.h" #include "llvm/CodeGen/CalcSpillWeights.h" #include "llvm/CodeGen/LiveIntervalAnalysis.h" #include "llvm/CodeGen/LiveStackAnalysis.h" @@ -46,7 +47,6 @@ #include "llvm/CodeGen/PBQP/Graph.h" #include "llvm/CodeGen/PBQP/Heuristics/Briggs.h" #include "llvm/CodeGen/RegAllocRegistry.h" -#include "llvm/CodeGen/RegisterCoalescer.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetInstrInfo.h" diff --git a/lib/CodeGen/RegisterCoalescer.cpp b/lib/CodeGen/RegisterCoalescer.cpp index 407559a..4b9c558 100644 --- a/lib/CodeGen/RegisterCoalescer.cpp +++ b/lib/CodeGen/RegisterCoalescer.cpp @@ -13,7 +13,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/CodeGen/RegisterCoalescer.h" +#include "RegisterCoalescer.h" #include "llvm/CodeGen/LiveIntervalAnalysis.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineRegisterInfo.h" diff --git a/lib/CodeGen/RegisterCoalescer.h b/lib/CodeGen/RegisterCoalescer.h new file mode 100644 index 0000000..af0b394 --- /dev/null +++ b/lib/CodeGen/RegisterCoalescer.h @@ -0,0 +1,244 @@ +//===-- RegisterCoalescer.h - Register Coalescing Interface ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the abstract interface for register coalescers, +// allowing them to interact with and query register allocators. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/IncludeFile.h" +#include "llvm/CodeGen/LiveInterval.h" +#include "llvm/ADT/SmallPtrSet.h" + +#ifndef LLVM_CODEGEN_REGISTER_COALESCER_H +#define LLVM_CODEGEN_REGISTER_COALESCER_H + +namespace llvm { + + class MachineFunction; + class RegallocQuery; + class AnalysisUsage; + class MachineInstr; + class TargetRegisterInfo; + class TargetRegisterClass; + class TargetInstrInfo; + + /// An abstract interface for register coalescers. Coalescers must + /// implement this interface to be part of the coalescer analysis + /// group. + class RegisterCoalescer { + public: + static char ID; // Class identification, replacement for typeinfo + RegisterCoalescer() {} + virtual ~RegisterCoalescer(); // We want to be subclassed + + /// Run the coalescer on this function, providing interference + /// data to query. Return whether we removed any copies. + virtual bool coalesceFunction(MachineFunction &mf, + RegallocQuery &ifd) = 0; + + /// Reset state. Can be used to allow a coalescer run by + /// PassManager to be run again by the register allocator. + virtual void reset(MachineFunction &mf) {} + + /// Register allocators must call this from their own + /// getAnalysisUsage to cover the case where the coalescer is not + /// a Pass in the proper sense and isn't managed by PassManager. + /// PassManager needs to know which analyses to make available and + /// which to invalidate when running the register allocator or any + /// pass that might call coalescing. The long-term solution is to + /// allow hierarchies of PassManagers. + virtual void getAnalysisUsage(AnalysisUsage &AU) const {} + }; + + /// An abstract interface for register allocators to interact with + /// coalescers + /// + /// Example: + /// + /// This is simply an example of how to use the RegallocQuery + /// interface. It is not meant to be used in production. + /// + /// class LinearScanRegallocQuery : public RegallocQuery { + /// private: + /// const LiveIntervals \&li; + /// + /// public: + /// LinearScanRegallocQuery(LiveIntervals &intervals) + /// : li(intervals) {} + /// + /// /// This is pretty slow and conservative, but since linear scan + /// /// allocation doesn't pre-compute interference information it's + /// /// the best we can do. Coalescers are always free to ignore this + /// /// and implement their own discovery strategy. See + /// /// SimpleRegisterCoalescing for an example. + /// void getInterferences(IntervalSet &interferences, + /// const LiveInterval &a) const { + /// for(LiveIntervals::const_iterator iv = li.begin(), + /// ivend = li.end(); + /// iv != ivend; + /// ++iv) { + /// if (interfere(a, iv->second)) { + /// interferences.insert(&iv->second); + /// } + /// } + /// } + /// + /// /// This is *really* slow and stupid. See above. + /// int getNumberOfInterferences(const LiveInterval &a) const { + /// IntervalSet intervals; + /// getInterferences(intervals, a); + /// return intervals.size(); + /// } + /// }; + /// + /// In the allocator: + /// + /// RegisterCoalescer &coalescer = getAnalysis(); + /// + /// // We don't reset the coalescer so if it's already been run this + /// // takes almost no time. + /// LinearScanRegallocQuery ifd(*li_); + /// coalescer.coalesceFunction(fn, ifd); + /// + class RegallocQuery { + public: + typedef SmallPtrSet IntervalSet; + + virtual ~RegallocQuery() {} + + /// Return whether two live ranges interfere. + virtual bool interfere(const LiveInterval &a, + const LiveInterval &b) const { + // A naive test + return a.overlaps(b); + } + + /// Return the set of intervals that interfere with this one. + virtual void getInterferences(IntervalSet &interferences, + const LiveInterval &a) const = 0; + + /// This can often be cheaper than actually returning the + /// interferences. + virtual int getNumberOfInterferences(const LiveInterval &a) const = 0; + + /// Make any data structure updates necessary to reflect + /// coalescing or other modifications. + virtual void updateDataForMerge(const LiveInterval &a, + const LiveInterval &b, + const MachineInstr ©) {} + + /// Allow the register allocator to communicate when it doesn't + /// want a copy coalesced. This may be due to assumptions made by + /// the allocator about various invariants and so this question is + /// a matter of legality, not performance. Performance decisions + /// about which copies to coalesce should be made by the + /// coalescer. + virtual bool isLegalToCoalesce(const MachineInstr &inst) const { + return true; + } + }; + + + /// CoalescerPair - A helper class for register coalescers. When deciding if + /// two registers can be coalesced, CoalescerPair can determine if a copy + /// instruction would become an identity copy after coalescing. + class CoalescerPair { + const TargetInstrInfo &tii_; + const TargetRegisterInfo &tri_; + + /// dstReg_ - The register that will be left after coalescing. It can be a + /// virtual or physical register. + unsigned dstReg_; + + /// srcReg_ - the virtual register that will be coalesced into dstReg. + unsigned srcReg_; + + /// subReg_ - The subregister index of srcReg in dstReg_. It is possible the + /// coalesce srcReg_ into a subreg of the larger dstReg_ when dstReg_ is a + /// virtual register. + unsigned subIdx_; + + /// partial_ - True when the original copy was a partial subregister copy. + bool partial_; + + /// crossClass_ - True when both regs are virtual, and newRC is constrained. + bool crossClass_; + + /// flipped_ - True when DstReg and SrcReg are reversed from the oriignal copy + /// instruction. + bool flipped_; + + /// newRC_ - The register class of the coalesced register, or NULL if dstReg_ + /// is a physreg. + const TargetRegisterClass *newRC_; + + /// compose - Compose subreg indices a and b, either may be 0. + unsigned compose(unsigned, unsigned) const; + + /// isMoveInstr - Return true if MI is a move or subreg instruction. + bool isMoveInstr(const MachineInstr *MI, unsigned &Src, unsigned &Dst, + unsigned &SrcSub, unsigned &DstSub) const; + + public: + CoalescerPair(const TargetInstrInfo &tii, const TargetRegisterInfo &tri) + : tii_(tii), tri_(tri), dstReg_(0), srcReg_(0), subIdx_(0), + partial_(false), crossClass_(false), flipped_(false), newRC_(0) {} + + /// setRegisters - set registers to match the copy instruction MI. Return + /// false if MI is not a coalescable copy instruction. + bool setRegisters(const MachineInstr*); + + /// flip - Swap srcReg_ and dstReg_. Return false if swapping is impossible + /// because dstReg_ is a physical register, or subIdx_ is set. + bool flip(); + + /// isCoalescable - Return true if MI is a copy instruction that will become + /// an identity copy after coalescing. + bool isCoalescable(const MachineInstr*) const; + + /// isPhys - Return true if DstReg is a physical register. + bool isPhys() const { return !newRC_; } + + /// isPartial - Return true if the original copy instruction did not copy the + /// full register, but was a subreg operation. + bool isPartial() const { return partial_; } + + /// isCrossClass - Return true if DstReg is virtual and NewRC is a smaller register class than DstReg's. + bool isCrossClass() const { return crossClass_; } + + /// isFlipped - Return true when getSrcReg is the register being defined by + /// the original copy instruction. + bool isFlipped() const { return flipped_; } + + /// getDstReg - Return the register (virtual or physical) that will remain + /// after coalescing. + unsigned getDstReg() const { return dstReg_; } + + /// getSrcReg - Return the virtual register that will be coalesced away. + unsigned getSrcReg() const { return srcReg_; } + + /// getSubIdx - Return the subregister index in DstReg that SrcReg will be + /// coalesced into, or 0. + unsigned getSubIdx() const { return subIdx_; } + + /// getNewRC - Return the register class of the coalesced register. + const TargetRegisterClass *getNewRC() const { return newRC_; } + }; +} + +// Because of the way .a files work, we must force the SimpleRC +// implementation to be pulled in if the RegisterCoalescing header is +// included. Otherwise we run the risk of RegisterCoalescing being +// used, but the default implementation not being linked into the tool +// that uses it. +FORCE_DEFINING_FILE_TO_BE_LINKED(RegisterCoalescer) +FORCE_DEFINING_FILE_TO_BE_LINKED(SimpleRegisterCoalescing) + +#endif diff --git a/lib/CodeGen/SimpleRegisterCoalescing.cpp b/lib/CodeGen/SimpleRegisterCoalescing.cpp index f58077b..f9b1b5b 100644 --- a/lib/CodeGen/SimpleRegisterCoalescing.cpp +++ b/lib/CodeGen/SimpleRegisterCoalescing.cpp @@ -16,6 +16,7 @@ #include "SimpleRegisterCoalescing.h" #include "VirtRegMap.h" #include "LiveDebugVariables.h" +#include "RegisterCoalescer.h" #include "llvm/CodeGen/LiveIntervalAnalysis.h" #include "llvm/Value.h" #include "llvm/Analysis/AliasAnalysis.h" @@ -24,7 +25,6 @@ #include "llvm/CodeGen/MachineLoopInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/Passes.h" -#include "llvm/CodeGen/RegisterCoalescer.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" diff --git a/lib/CodeGen/SimpleRegisterCoalescing.h b/lib/CodeGen/SimpleRegisterCoalescing.h index 5c6738b..6b07216 100644 --- a/lib/CodeGen/SimpleRegisterCoalescing.h +++ b/lib/CodeGen/SimpleRegisterCoalescing.h @@ -14,10 +14,10 @@ #ifndef LLVM_CODEGEN_SIMPLE_REGISTER_COALESCING_H #define LLVM_CODEGEN_SIMPLE_REGISTER_COALESCING_H +#include "RegisterCoalescer.h" +#include "RegisterClassInfo.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/LiveIntervalAnalysis.h" -#include "llvm/CodeGen/RegisterCoalescer.h" -#include "RegisterClassInfo.h" namespace llvm { class SimpleRegisterCoalescing; -- cgit v1.1 From b0efa94fb63d55c7aa5eb3c7c23d39a763036c24 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Sun, 26 Jun 2011 21:54:28 +0000 Subject: merge SimpleRegisterCoalescing.h into RegisterCoalescer.h. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133896 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/RegisterCoalescer.h | 128 +++++++++++++++++++++++++- lib/CodeGen/SimpleRegisterCoalescing.cpp | 2 +- lib/CodeGen/SimpleRegisterCoalescing.h | 153 ------------------------------- lib/CodeGen/Splitter.cpp | 2 +- 4 files changed, 129 insertions(+), 156 deletions(-) delete mode 100644 lib/CodeGen/SimpleRegisterCoalescing.h diff --git a/lib/CodeGen/RegisterCoalescer.h b/lib/CodeGen/RegisterCoalescer.h index af0b394..739a4c3 100644 --- a/lib/CodeGen/RegisterCoalescer.h +++ b/lib/CodeGen/RegisterCoalescer.h @@ -12,6 +12,7 @@ // //===----------------------------------------------------------------------===// +#include "RegisterClassInfo.h" #include "llvm/Support/IncludeFile.h" #include "llvm/CodeGen/LiveInterval.h" #include "llvm/ADT/SmallPtrSet.h" @@ -28,6 +29,10 @@ namespace llvm { class TargetRegisterInfo; class TargetRegisterClass; class TargetInstrInfo; + class SimpleRegisterCoalescing; + class LiveDebugVariables; + class VirtRegMap; + class MachineLoopInfo; /// An abstract interface for register coalescers. Coalescers must /// implement this interface to be part of the coalescer analysis @@ -231,7 +236,128 @@ namespace llvm { /// getNewRC - Return the register class of the coalesced register. const TargetRegisterClass *getNewRC() const { return newRC_; } }; -} + + class SimpleRegisterCoalescing : public MachineFunctionPass, + public RegisterCoalescer { + MachineFunction* mf_; + MachineRegisterInfo* mri_; + const TargetMachine* tm_; + const TargetRegisterInfo* tri_; + const TargetInstrInfo* tii_; + LiveIntervals *li_; + LiveDebugVariables *ldv_; + const MachineLoopInfo* loopInfo; + AliasAnalysis *AA; + RegisterClassInfo RegClassInfo; + + /// JoinedCopies - Keep track of copies eliminated due to coalescing. + /// + SmallPtrSet JoinedCopies; + + /// ReMatCopies - Keep track of copies eliminated due to remat. + /// + SmallPtrSet ReMatCopies; + + /// ReMatDefs - Keep track of definition instructions which have + /// been remat'ed. + SmallPtrSet ReMatDefs; + + public: + static char ID; // Pass identifcation, replacement for typeid + SimpleRegisterCoalescing() : MachineFunctionPass(ID) { + initializeSimpleRegisterCoalescingPass(*PassRegistry::getPassRegistry()); + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + virtual void releaseMemory(); + + /// runOnMachineFunction - pass entry point + virtual bool runOnMachineFunction(MachineFunction&); + + bool coalesceFunction(MachineFunction &mf, RegallocQuery &) { + // This runs as an independent pass, so don't do anything. + return false; + } + + /// print - Implement the dump method. + virtual void print(raw_ostream &O, const Module* = 0) const; + + private: + /// joinIntervals - join compatible live intervals + void joinIntervals(); + + /// CopyCoalesceInMBB - Coalesce copies in the specified MBB, putting + /// copies that cannot yet be coalesced into the "TryAgain" list. + void CopyCoalesceInMBB(MachineBasicBlock *MBB, + std::vector &TryAgain); + + /// JoinCopy - Attempt to join intervals corresponding to SrcReg/DstReg, + /// which are the src/dst of the copy instruction CopyMI. This returns true + /// if the copy was successfully coalesced away. If it is not currently + /// possible to coalesce this interval, but it may be possible if other + /// things get coalesced, then it returns true by reference in 'Again'. + bool JoinCopy(MachineInstr *TheCopy, bool &Again); + + /// JoinIntervals - Attempt to join these two intervals. On failure, this + /// returns false. The output "SrcInt" will not have been modified, so we can + /// use this information below to update aliases. + bool JoinIntervals(CoalescerPair &CP); + + /// AdjustCopiesBackFrom - We found a non-trivially-coalescable copy. If + /// the source value number is defined by a copy from the destination reg + /// see if we can merge these two destination reg valno# into a single + /// value number, eliminating a copy. + bool AdjustCopiesBackFrom(const CoalescerPair &CP, MachineInstr *CopyMI); + + /// HasOtherReachingDefs - Return true if there are definitions of IntB + /// other than BValNo val# that can reach uses of AValno val# of IntA. + bool HasOtherReachingDefs(LiveInterval &IntA, LiveInterval &IntB, + VNInfo *AValNo, VNInfo *BValNo); + + /// RemoveCopyByCommutingDef - We found a non-trivially-coalescable copy. + /// If the source value number is defined by a commutable instruction and + /// its other operand is coalesced to the copy dest register, see if we + /// can transform the copy into a noop by commuting the definition. + bool RemoveCopyByCommutingDef(const CoalescerPair &CP,MachineInstr *CopyMI); + + /// ReMaterializeTrivialDef - If the source of a copy is defined by a trivial + /// computation, replace the copy by rematerialize the definition. + /// If PreserveSrcInt is true, make sure SrcInt is valid after the call. + bool ReMaterializeTrivialDef(LiveInterval &SrcInt, bool PreserveSrcInt, + unsigned DstReg, unsigned DstSubIdx, + MachineInstr *CopyMI); + + /// shouldJoinPhys - Return true if a physreg copy should be joined. + bool shouldJoinPhys(CoalescerPair &CP); + + /// isWinToJoinCrossClass - Return true if it's profitable to coalesce + /// two virtual registers from different register classes. + bool isWinToJoinCrossClass(unsigned SrcReg, + unsigned DstReg, + const TargetRegisterClass *SrcRC, + const TargetRegisterClass *DstRC, + const TargetRegisterClass *NewRC); + + /// UpdateRegDefsUses - Replace all defs and uses of SrcReg to DstReg and + /// update the subregister number if it is not zero. If DstReg is a + /// physical register and the existing subregister number of the def / use + /// being updated is not zero, make sure to set it to the correct physical + /// subregister. + void UpdateRegDefsUses(const CoalescerPair &CP); + + /// RemoveDeadDef - If a def of a live interval is now determined dead, + /// remove the val# it defines. If the live interval becomes empty, remove + /// it as well. + bool RemoveDeadDef(LiveInterval &li, MachineInstr *DefMI); + + /// RemoveCopyFlag - If DstReg is no longer defined by CopyMI, clear the + /// VNInfo copy flag for DstReg and all aliases. + void RemoveCopyFlag(unsigned DstReg, const MachineInstr *CopyMI); + + /// markAsJoined - Remember that CopyMI has already been joined. + void markAsJoined(MachineInstr *CopyMI); + }; +} // End llvm namespace // Because of the way .a files work, we must force the SimpleRC // implementation to be pulled in if the RegisterCoalescing header is diff --git a/lib/CodeGen/SimpleRegisterCoalescing.cpp b/lib/CodeGen/SimpleRegisterCoalescing.cpp index f9b1b5b..8283965 100644 --- a/lib/CodeGen/SimpleRegisterCoalescing.cpp +++ b/lib/CodeGen/SimpleRegisterCoalescing.cpp @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "regcoalescing" -#include "SimpleRegisterCoalescing.h" +#include "RegisterCoalescer.h" #include "VirtRegMap.h" #include "LiveDebugVariables.h" #include "RegisterCoalescer.h" diff --git a/lib/CodeGen/SimpleRegisterCoalescing.h b/lib/CodeGen/SimpleRegisterCoalescing.h deleted file mode 100644 index 6b07216..0000000 --- a/lib/CodeGen/SimpleRegisterCoalescing.h +++ /dev/null @@ -1,153 +0,0 @@ -//===-- SimpleRegisterCoalescing.h - Register Coalescing --------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements a simple register copy coalescing phase. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_SIMPLE_REGISTER_COALESCING_H -#define LLVM_CODEGEN_SIMPLE_REGISTER_COALESCING_H - -#include "RegisterCoalescer.h" -#include "RegisterClassInfo.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/LiveIntervalAnalysis.h" - -namespace llvm { - class SimpleRegisterCoalescing; - class LiveDebugVariables; - class TargetRegisterInfo; - class TargetInstrInfo; - class VirtRegMap; - class MachineLoopInfo; - - class SimpleRegisterCoalescing : public MachineFunctionPass, - public RegisterCoalescer { - MachineFunction* mf_; - MachineRegisterInfo* mri_; - const TargetMachine* tm_; - const TargetRegisterInfo* tri_; - const TargetInstrInfo* tii_; - LiveIntervals *li_; - LiveDebugVariables *ldv_; - const MachineLoopInfo* loopInfo; - AliasAnalysis *AA; - RegisterClassInfo RegClassInfo; - - /// JoinedCopies - Keep track of copies eliminated due to coalescing. - /// - SmallPtrSet JoinedCopies; - - /// ReMatCopies - Keep track of copies eliminated due to remat. - /// - SmallPtrSet ReMatCopies; - - /// ReMatDefs - Keep track of definition instructions which have - /// been remat'ed. - SmallPtrSet ReMatDefs; - - public: - static char ID; // Pass identifcation, replacement for typeid - SimpleRegisterCoalescing() : MachineFunctionPass(ID) { - initializeSimpleRegisterCoalescingPass(*PassRegistry::getPassRegistry()); - } - - virtual void getAnalysisUsage(AnalysisUsage &AU) const; - virtual void releaseMemory(); - - /// runOnMachineFunction - pass entry point - virtual bool runOnMachineFunction(MachineFunction&); - - bool coalesceFunction(MachineFunction &mf, RegallocQuery &) { - // This runs as an independent pass, so don't do anything. - return false; - } - - /// print - Implement the dump method. - virtual void print(raw_ostream &O, const Module* = 0) const; - - private: - /// joinIntervals - join compatible live intervals - void joinIntervals(); - - /// CopyCoalesceInMBB - Coalesce copies in the specified MBB, putting - /// copies that cannot yet be coalesced into the "TryAgain" list. - void CopyCoalesceInMBB(MachineBasicBlock *MBB, - std::vector &TryAgain); - - /// JoinCopy - Attempt to join intervals corresponding to SrcReg/DstReg, - /// which are the src/dst of the copy instruction CopyMI. This returns true - /// if the copy was successfully coalesced away. If it is not currently - /// possible to coalesce this interval, but it may be possible if other - /// things get coalesced, then it returns true by reference in 'Again'. - bool JoinCopy(MachineInstr *TheCopy, bool &Again); - - /// JoinIntervals - Attempt to join these two intervals. On failure, this - /// returns false. The output "SrcInt" will not have been modified, so we can - /// use this information below to update aliases. - bool JoinIntervals(CoalescerPair &CP); - - /// AdjustCopiesBackFrom - We found a non-trivially-coalescable copy. If - /// the source value number is defined by a copy from the destination reg - /// see if we can merge these two destination reg valno# into a single - /// value number, eliminating a copy. - bool AdjustCopiesBackFrom(const CoalescerPair &CP, MachineInstr *CopyMI); - - /// HasOtherReachingDefs - Return true if there are definitions of IntB - /// other than BValNo val# that can reach uses of AValno val# of IntA. - bool HasOtherReachingDefs(LiveInterval &IntA, LiveInterval &IntB, - VNInfo *AValNo, VNInfo *BValNo); - - /// RemoveCopyByCommutingDef - We found a non-trivially-coalescable copy. - /// If the source value number is defined by a commutable instruction and - /// its other operand is coalesced to the copy dest register, see if we - /// can transform the copy into a noop by commuting the definition. - bool RemoveCopyByCommutingDef(const CoalescerPair &CP,MachineInstr *CopyMI); - - /// ReMaterializeTrivialDef - If the source of a copy is defined by a trivial - /// computation, replace the copy by rematerialize the definition. - /// If PreserveSrcInt is true, make sure SrcInt is valid after the call. - bool ReMaterializeTrivialDef(LiveInterval &SrcInt, bool PreserveSrcInt, - unsigned DstReg, unsigned DstSubIdx, - MachineInstr *CopyMI); - - /// shouldJoinPhys - Return true if a physreg copy should be joined. - bool shouldJoinPhys(CoalescerPair &CP); - - /// isWinToJoinCrossClass - Return true if it's profitable to coalesce - /// two virtual registers from different register classes. - bool isWinToJoinCrossClass(unsigned SrcReg, - unsigned DstReg, - const TargetRegisterClass *SrcRC, - const TargetRegisterClass *DstRC, - const TargetRegisterClass *NewRC); - - /// UpdateRegDefsUses - Replace all defs and uses of SrcReg to DstReg and - /// update the subregister number if it is not zero. If DstReg is a - /// physical register and the existing subregister number of the def / use - /// being updated is not zero, make sure to set it to the correct physical - /// subregister. - void UpdateRegDefsUses(const CoalescerPair &CP); - - /// RemoveDeadDef - If a def of a live interval is now determined dead, - /// remove the val# it defines. If the live interval becomes empty, remove - /// it as well. - bool RemoveDeadDef(LiveInterval &li, MachineInstr *DefMI); - - /// RemoveCopyFlag - If DstReg is no longer defined by CopyMI, clear the - /// VNInfo copy flag for DstReg and all aliases. - void RemoveCopyFlag(unsigned DstReg, const MachineInstr *CopyMI); - - /// markAsJoined - Remember that CopyMI has already been joined. - void markAsJoined(MachineInstr *CopyMI); - }; - -} // End llvm namespace - -#endif diff --git a/lib/CodeGen/Splitter.cpp b/lib/CodeGen/Splitter.cpp index 08aee82..ec75df4 100644 --- a/lib/CodeGen/Splitter.cpp +++ b/lib/CodeGen/Splitter.cpp @@ -11,7 +11,7 @@ #include "Splitter.h" -#include "SimpleRegisterCoalescing.h" +#include "RegisterCoalescer.h" #include "llvm/Module.h" #include "llvm/CodeGen/CalcSpillWeights.h" #include "llvm/CodeGen/LiveIntervalAnalysis.h" -- cgit v1.1 From 655739de7b09dcfecd9f3e5f1734e53ec90a19f3 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Sun, 26 Jun 2011 22:06:36 +0000 Subject: Merge SimpleRegisterCoalescing.cpp into RegisterCoalescer.cpp. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133897 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CMakeLists.txt | 1 - lib/CodeGen/RegisterCoalescer.cpp | 1525 ++++++++++++++++++++++++++++- lib/CodeGen/SimpleRegisterCoalescing.cpp | 1538 ------------------------------ 3 files changed, 1523 insertions(+), 1541 deletions(-) delete mode 100644 lib/CodeGen/SimpleRegisterCoalescing.cpp diff --git a/lib/CodeGen/CMakeLists.txt b/lib/CodeGen/CMakeLists.txt index aef4ff2..dae429c 100644 --- a/lib/CodeGen/CMakeLists.txt +++ b/lib/CodeGen/CMakeLists.txt @@ -79,7 +79,6 @@ add_llvm_library(LLVMCodeGen ScoreboardHazardRecognizer.cpp ShadowStackGC.cpp ShrinkWrapping.cpp - SimpleRegisterCoalescing.cpp SjLjEHPrepare.cpp SlotIndexes.cpp Spiller.cpp diff --git a/lib/CodeGen/RegisterCoalescer.cpp b/lib/CodeGen/RegisterCoalescer.cpp index 4b9c558..d0dcbb5 100644 --- a/lib/CodeGen/RegisterCoalescer.cpp +++ b/lib/CodeGen/RegisterCoalescer.cpp @@ -13,16 +13,86 @@ // //===----------------------------------------------------------------------===// +#define DEBUG_TYPE "regcoalescing" #include "RegisterCoalescer.h" +#include "VirtRegMap.h" +#include "LiveDebugVariables.h" + +#include "llvm/Pass.h" +#include "llvm/Value.h" #include "llvm/CodeGen/LiveIntervalAnalysis.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetRegisterInfo.h" -#include "llvm/Pass.h" - +#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/STLExtras.h" +#include +#include using namespace llvm; +STATISTIC(numJoins , "Number of interval joins performed"); +STATISTIC(numCrossRCs , "Number of cross class joins performed"); +STATISTIC(numCommutes , "Number of instruction commuting performed"); +STATISTIC(numExtends , "Number of copies extended"); +STATISTIC(NumReMats , "Number of instructions re-materialized"); +STATISTIC(numPeep , "Number of identity moves eliminated after coalescing"); +STATISTIC(numAborts , "Number of times interval joining aborted"); + +char SimpleRegisterCoalescing::ID = 0; +static cl::opt +EnableJoining("join-liveintervals", + cl::desc("Coalesce copies (default=true)"), + cl::init(true)); + +static cl::opt +DisableCrossClassJoin("disable-cross-class-join", + cl::desc("Avoid coalescing cross register class copies"), + cl::init(false), cl::Hidden); + +static cl::opt +EnablePhysicalJoin("join-physregs", + cl::desc("Join physical register copies"), + cl::init(false), cl::Hidden); + +static cl::opt +VerifyCoalescing("verify-coalescing", + cl::desc("Verify machine instrs before and after register coalescing"), + cl::Hidden); + +INITIALIZE_AG_PASS_BEGIN(SimpleRegisterCoalescing, RegisterCoalescer, + "simple-register-coalescing", "Simple Register Coalescing", + false, false, true) +INITIALIZE_PASS_DEPENDENCY(LiveIntervals) +INITIALIZE_PASS_DEPENDENCY(LiveDebugVariables) +INITIALIZE_PASS_DEPENDENCY(SlotIndexes) +INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo) +INITIALIZE_PASS_DEPENDENCY(StrongPHIElimination) +INITIALIZE_PASS_DEPENDENCY(PHIElimination) +INITIALIZE_PASS_DEPENDENCY(TwoAddressInstructionPass) +INITIALIZE_AG_DEPENDENCY(AliasAnalysis) +INITIALIZE_AG_PASS_END(SimpleRegisterCoalescing, RegisterCoalescer, + "simple-register-coalescing", "Simple Register Coalescing", + false, false, true) + +char &llvm::SimpleRegisterCoalescingID = SimpleRegisterCoalescing::ID; + // Register the RegisterCoalescer interface, providing a nice name to refer to. INITIALIZE_ANALYSIS_GROUP(RegisterCoalescer, "Register Coalescer", SimpleRegisterCoalescing) @@ -195,3 +265,1454 @@ bool CoalescerPair::isCoalescable(const MachineInstr *MI) const { // used, but the default implementation not being linked into the tool // that uses it. DEFINING_FILE_FOR(RegisterCoalescer) + +void SimpleRegisterCoalescing::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + AU.addRequired(); + AU.addRequired(); + AU.addPreserved(); + AU.addRequired(); + AU.addPreserved(); + AU.addPreserved(); + AU.addRequired(); + AU.addPreserved(); + AU.addPreservedID(MachineDominatorsID); + AU.addPreservedID(StrongPHIEliminationID); + AU.addPreservedID(PHIEliminationID); + AU.addPreservedID(TwoAddressInstructionPassID); + MachineFunctionPass::getAnalysisUsage(AU); +} + +void SimpleRegisterCoalescing::markAsJoined(MachineInstr *CopyMI) { + /// Joined copies are not deleted immediately, but kept in JoinedCopies. + JoinedCopies.insert(CopyMI); + + /// Mark all register operands of CopyMI as so they won't affect dead + /// code elimination. + for (MachineInstr::mop_iterator I = CopyMI->operands_begin(), + E = CopyMI->operands_end(); I != E; ++I) + if (I->isReg()) + I->setIsUndef(true); +} + +/// AdjustCopiesBackFrom - We found a non-trivially-coalescable copy with IntA +/// being the source and IntB being the dest, thus this defines a value number +/// in IntB. If the source value number (in IntA) is defined by a copy from B, +/// see if we can merge these two pieces of B into a single value number, +/// eliminating a copy. For example: +/// +/// A3 = B0 +/// ... +/// B1 = A3 <- this copy +/// +/// In this case, B0 can be extended to where the B1 copy lives, allowing the B1 +/// value number to be replaced with B0 (which simplifies the B liveinterval). +/// +/// This returns true if an interval was modified. +/// +bool SimpleRegisterCoalescing::AdjustCopiesBackFrom(const CoalescerPair &CP, + MachineInstr *CopyMI) { + // Bail if there is no dst interval - can happen when merging physical subreg + // operations. + if (!li_->hasInterval(CP.getDstReg())) + return false; + + LiveInterval &IntA = + li_->getInterval(CP.isFlipped() ? CP.getDstReg() : CP.getSrcReg()); + LiveInterval &IntB = + li_->getInterval(CP.isFlipped() ? CP.getSrcReg() : CP.getDstReg()); + SlotIndex CopyIdx = li_->getInstructionIndex(CopyMI).getDefIndex(); + + // BValNo is a value number in B that is defined by a copy from A. 'B3' in + // the example above. + LiveInterval::iterator BLR = IntB.FindLiveRangeContaining(CopyIdx); + if (BLR == IntB.end()) return false; + VNInfo *BValNo = BLR->valno; + + // Get the location that B is defined at. Two options: either this value has + // an unknown definition point or it is defined at CopyIdx. If unknown, we + // can't process it. + if (!BValNo->isDefByCopy()) return false; + assert(BValNo->def == CopyIdx && "Copy doesn't define the value?"); + + // AValNo is the value number in A that defines the copy, A3 in the example. + SlotIndex CopyUseIdx = CopyIdx.getUseIndex(); + LiveInterval::iterator ALR = IntA.FindLiveRangeContaining(CopyUseIdx); + // The live range might not exist after fun with physreg coalescing. + if (ALR == IntA.end()) return false; + VNInfo *AValNo = ALR->valno; + // If it's re-defined by an early clobber somewhere in the live range, then + // it's not safe to eliminate the copy. FIXME: This is a temporary workaround. + // See PR3149: + // 172 %ECX = MOV32rr %reg1039 + // 180 INLINEASM , 10, %EAX, 14, %ECX, 9, + // %EAX, + // 36, , 1, %reg0, 0, 9, %ECX, 36, , 1, %reg0, 0 + // 188 %EAX = MOV32rr %EAX + // 196 %ECX = MOV32rr %ECX + // 204 %ECX = MOV32rr %ECX + // 212 %EAX = MOV32rr %EAX + // 220 %EAX = MOV32rr %EAX + // 228 %reg1039 = MOV32rr %ECX + // The early clobber operand ties ECX input to the ECX def. + // + // The live interval of ECX is represented as this: + // %reg20,inf = [46,47:1)[174,230:0) 0@174-(230) 1@46-(47) + // The coalescer has no idea there was a def in the middle of [174,230]. + if (AValNo->hasRedefByEC()) + return false; + + // If AValNo is defined as a copy from IntB, we can potentially process this. + // Get the instruction that defines this value number. + if (!CP.isCoalescable(AValNo->getCopy())) + return false; + + // Get the LiveRange in IntB that this value number starts with. + LiveInterval::iterator ValLR = + IntB.FindLiveRangeContaining(AValNo->def.getPrevSlot()); + if (ValLR == IntB.end()) + return false; + + // Make sure that the end of the live range is inside the same block as + // CopyMI. + MachineInstr *ValLREndInst = + li_->getInstructionFromIndex(ValLR->end.getPrevSlot()); + if (!ValLREndInst || ValLREndInst->getParent() != CopyMI->getParent()) + return false; + + // Okay, we now know that ValLR ends in the same block that the CopyMI + // live-range starts. If there are no intervening live ranges between them in + // IntB, we can merge them. + if (ValLR+1 != BLR) return false; + + // If a live interval is a physical register, conservatively check if any + // of its aliases is overlapping the live interval of the virtual register. + // If so, do not coalesce. + if (TargetRegisterInfo::isPhysicalRegister(IntB.reg)) { + for (const unsigned *AS = tri_->getAliasSet(IntB.reg); *AS; ++AS) + if (li_->hasInterval(*AS) && IntA.overlaps(li_->getInterval(*AS))) { + DEBUG({ + dbgs() << "\t\tInterfere with alias "; + li_->getInterval(*AS).print(dbgs(), tri_); + }); + return false; + } + } + + DEBUG({ + dbgs() << "Extending: "; + IntB.print(dbgs(), tri_); + }); + + SlotIndex FillerStart = ValLR->end, FillerEnd = BLR->start; + // We are about to delete CopyMI, so need to remove it as the 'instruction + // that defines this value #'. Update the valnum with the new defining + // instruction #. + BValNo->def = FillerStart; + BValNo->setCopy(0); + + // Okay, we can merge them. We need to insert a new liverange: + // [ValLR.end, BLR.begin) of either value number, then we merge the + // two value numbers. + IntB.addRange(LiveRange(FillerStart, FillerEnd, BValNo)); + + // If the IntB live range is assigned to a physical register, and if that + // physreg has sub-registers, update their live intervals as well. + if (TargetRegisterInfo::isPhysicalRegister(IntB.reg)) { + for (const unsigned *SR = tri_->getSubRegisters(IntB.reg); *SR; ++SR) { + if (!li_->hasInterval(*SR)) + continue; + LiveInterval &SRLI = li_->getInterval(*SR); + SRLI.addRange(LiveRange(FillerStart, FillerEnd, + SRLI.getNextValue(FillerStart, 0, + li_->getVNInfoAllocator()))); + } + } + + // Okay, merge "B1" into the same value number as "B0". + if (BValNo != ValLR->valno) { + // If B1 is killed by a PHI, then the merged live range must also be killed + // by the same PHI, as B0 and B1 can not overlap. + bool HasPHIKill = BValNo->hasPHIKill(); + IntB.MergeValueNumberInto(BValNo, ValLR->valno); + if (HasPHIKill) + ValLR->valno->setHasPHIKill(true); + } + DEBUG({ + dbgs() << " result = "; + IntB.print(dbgs(), tri_); + dbgs() << "\n"; + }); + + // If the source instruction was killing the source register before the + // merge, unset the isKill marker given the live range has been extended. + int UIdx = ValLREndInst->findRegisterUseOperandIdx(IntB.reg, true); + if (UIdx != -1) { + ValLREndInst->getOperand(UIdx).setIsKill(false); + } + + // If the copy instruction was killing the destination register before the + // merge, find the last use and trim the live range. That will also add the + // isKill marker. + if (ALR->end == CopyIdx) + li_->shrinkToUses(&IntA); + + ++numExtends; + return true; +} + +/// HasOtherReachingDefs - Return true if there are definitions of IntB +/// other than BValNo val# that can reach uses of AValno val# of IntA. +bool SimpleRegisterCoalescing::HasOtherReachingDefs(LiveInterval &IntA, + LiveInterval &IntB, + VNInfo *AValNo, + VNInfo *BValNo) { + for (LiveInterval::iterator AI = IntA.begin(), AE = IntA.end(); + AI != AE; ++AI) { + if (AI->valno != AValNo) continue; + LiveInterval::Ranges::iterator BI = + std::upper_bound(IntB.ranges.begin(), IntB.ranges.end(), AI->start); + if (BI != IntB.ranges.begin()) + --BI; + for (; BI != IntB.ranges.end() && AI->end >= BI->start; ++BI) { + if (BI->valno == BValNo) + continue; + if (BI->start <= AI->start && BI->end > AI->start) + return true; + if (BI->start > AI->start && BI->start < AI->end) + return true; + } + } + return false; +} + +/// RemoveCopyByCommutingDef - We found a non-trivially-coalescable copy with +/// IntA being the source and IntB being the dest, thus this defines a value +/// number in IntB. If the source value number (in IntA) is defined by a +/// commutable instruction and its other operand is coalesced to the copy dest +/// register, see if we can transform the copy into a noop by commuting the +/// definition. For example, +/// +/// A3 = op A2 B0 +/// ... +/// B1 = A3 <- this copy +/// ... +/// = op A3 <- more uses +/// +/// ==> +/// +/// B2 = op B0 A2 +/// ... +/// B1 = B2 <- now an identify copy +/// ... +/// = op B2 <- more uses +/// +/// This returns true if an interval was modified. +/// +bool SimpleRegisterCoalescing::RemoveCopyByCommutingDef(const CoalescerPair &CP, + MachineInstr *CopyMI) { + // FIXME: For now, only eliminate the copy by commuting its def when the + // source register is a virtual register. We want to guard against cases + // where the copy is a back edge copy and commuting the def lengthen the + // live interval of the source register to the entire loop. + if (CP.isPhys() && CP.isFlipped()) + return false; + + // Bail if there is no dst interval. + if (!li_->hasInterval(CP.getDstReg())) + return false; + + SlotIndex CopyIdx = li_->getInstructionIndex(CopyMI).getDefIndex(); + + LiveInterval &IntA = + li_->getInterval(CP.isFlipped() ? CP.getDstReg() : CP.getSrcReg()); + LiveInterval &IntB = + li_->getInterval(CP.isFlipped() ? CP.getSrcReg() : CP.getDstReg()); + + // BValNo is a value number in B that is defined by a copy from A. 'B3' in + // the example above. + VNInfo *BValNo = IntB.getVNInfoAt(CopyIdx); + if (!BValNo || !BValNo->isDefByCopy()) + return false; + + assert(BValNo->def == CopyIdx && "Copy doesn't define the value?"); + + // AValNo is the value number in A that defines the copy, A3 in the example. + VNInfo *AValNo = IntA.getVNInfoAt(CopyIdx.getUseIndex()); + assert(AValNo && "COPY source not live"); + + // If other defs can reach uses of this def, then it's not safe to perform + // the optimization. + if (AValNo->isPHIDef() || AValNo->isUnused() || AValNo->hasPHIKill()) + return false; + MachineInstr *DefMI = li_->getInstructionFromIndex(AValNo->def); + if (!DefMI) + return false; + const TargetInstrDesc &TID = DefMI->getDesc(); + if (!TID.isCommutable()) + return false; + // If DefMI is a two-address instruction then commuting it will change the + // destination register. + int DefIdx = DefMI->findRegisterDefOperandIdx(IntA.reg); + assert(DefIdx != -1); + unsigned UseOpIdx; + if (!DefMI->isRegTiedToUseOperand(DefIdx, &UseOpIdx)) + return false; + unsigned Op1, Op2, NewDstIdx; + if (!tii_->findCommutedOpIndices(DefMI, Op1, Op2)) + return false; + if (Op1 == UseOpIdx) + NewDstIdx = Op2; + else if (Op2 == UseOpIdx) + NewDstIdx = Op1; + else + return false; + + MachineOperand &NewDstMO = DefMI->getOperand(NewDstIdx); + unsigned NewReg = NewDstMO.getReg(); + if (NewReg != IntB.reg || !NewDstMO.isKill()) + return false; + + // Make sure there are no other definitions of IntB that would reach the + // uses which the new definition can reach. + if (HasOtherReachingDefs(IntA, IntB, AValNo, BValNo)) + return false; + + // Abort if the aliases of IntB.reg have values that are not simply the + // clobbers from the superreg. + if (TargetRegisterInfo::isPhysicalRegister(IntB.reg)) + for (const unsigned *AS = tri_->getAliasSet(IntB.reg); *AS; ++AS) + if (li_->hasInterval(*AS) && + HasOtherReachingDefs(IntA, li_->getInterval(*AS), AValNo, 0)) + return false; + + // If some of the uses of IntA.reg is already coalesced away, return false. + // It's not possible to determine whether it's safe to perform the coalescing. + for (MachineRegisterInfo::use_nodbg_iterator UI = + mri_->use_nodbg_begin(IntA.reg), + UE = mri_->use_nodbg_end(); UI != UE; ++UI) { + MachineInstr *UseMI = &*UI; + SlotIndex UseIdx = li_->getInstructionIndex(UseMI); + LiveInterval::iterator ULR = IntA.FindLiveRangeContaining(UseIdx); + if (ULR == IntA.end()) + continue; + if (ULR->valno == AValNo && JoinedCopies.count(UseMI)) + return false; + } + + DEBUG(dbgs() << "\tRemoveCopyByCommutingDef: " << AValNo->def << '\t' + << *DefMI); + + // At this point we have decided that it is legal to do this + // transformation. Start by commuting the instruction. + MachineBasicBlock *MBB = DefMI->getParent(); + MachineInstr *NewMI = tii_->commuteInstruction(DefMI); + if (!NewMI) + return false; + if (TargetRegisterInfo::isVirtualRegister(IntA.reg) && + TargetRegisterInfo::isVirtualRegister(IntB.reg) && + !mri_->constrainRegClass(IntB.reg, mri_->getRegClass(IntA.reg))) + return false; + if (NewMI != DefMI) { + li_->ReplaceMachineInstrInMaps(DefMI, NewMI); + MBB->insert(DefMI, NewMI); + MBB->erase(DefMI); + } + unsigned OpIdx = NewMI->findRegisterUseOperandIdx(IntA.reg, false); + NewMI->getOperand(OpIdx).setIsKill(); + + // If ALR and BLR overlaps and end of BLR extends beyond end of ALR, e.g. + // A = or A, B + // ... + // B = A + // ... + // C = A + // ... + // = B + + // Update uses of IntA of the specific Val# with IntB. + for (MachineRegisterInfo::use_iterator UI = mri_->use_begin(IntA.reg), + UE = mri_->use_end(); UI != UE;) { + MachineOperand &UseMO = UI.getOperand(); + MachineInstr *UseMI = &*UI; + ++UI; + if (JoinedCopies.count(UseMI)) + continue; + if (UseMI->isDebugValue()) { + // FIXME These don't have an instruction index. Not clear we have enough + // info to decide whether to do this replacement or not. For now do it. + UseMO.setReg(NewReg); + continue; + } + SlotIndex UseIdx = li_->getInstructionIndex(UseMI).getUseIndex(); + LiveInterval::iterator ULR = IntA.FindLiveRangeContaining(UseIdx); + if (ULR == IntA.end() || ULR->valno != AValNo) + continue; + if (TargetRegisterInfo::isPhysicalRegister(NewReg)) + UseMO.substPhysReg(NewReg, *tri_); + else + UseMO.setReg(NewReg); + if (UseMI == CopyMI) + continue; + if (!UseMI->isCopy()) + continue; + if (UseMI->getOperand(0).getReg() != IntB.reg || + UseMI->getOperand(0).getSubReg()) + continue; + + // This copy will become a noop. If it's defining a new val#, merge it into + // BValNo. + SlotIndex DefIdx = UseIdx.getDefIndex(); + VNInfo *DVNI = IntB.getVNInfoAt(DefIdx); + if (!DVNI) + continue; + DEBUG(dbgs() << "\t\tnoop: " << DefIdx << '\t' << *UseMI); + assert(DVNI->def == DefIdx); + BValNo = IntB.MergeValueNumberInto(BValNo, DVNI); + markAsJoined(UseMI); + } + + // Extend BValNo by merging in IntA live ranges of AValNo. Val# definition + // is updated. + VNInfo *ValNo = BValNo; + ValNo->def = AValNo->def; + ValNo->setCopy(0); + for (LiveInterval::iterator AI = IntA.begin(), AE = IntA.end(); + AI != AE; ++AI) { + if (AI->valno != AValNo) continue; + IntB.addRange(LiveRange(AI->start, AI->end, ValNo)); + } + DEBUG(dbgs() << "\t\textended: " << IntB << '\n'); + + IntA.removeValNo(AValNo); + DEBUG(dbgs() << "\t\ttrimmed: " << IntA << '\n'); + ++numCommutes; + return true; +} + +/// ReMaterializeTrivialDef - If the source of a copy is defined by a trivial +/// computation, replace the copy by rematerialize the definition. +bool SimpleRegisterCoalescing::ReMaterializeTrivialDef(LiveInterval &SrcInt, + bool preserveSrcInt, + unsigned DstReg, + unsigned DstSubIdx, + MachineInstr *CopyMI) { + SlotIndex CopyIdx = li_->getInstructionIndex(CopyMI).getUseIndex(); + LiveInterval::iterator SrcLR = SrcInt.FindLiveRangeContaining(CopyIdx); + assert(SrcLR != SrcInt.end() && "Live range not found!"); + VNInfo *ValNo = SrcLR->valno; + // If other defs can reach uses of this def, then it's not safe to perform + // the optimization. + if (ValNo->isPHIDef() || ValNo->isUnused() || ValNo->hasPHIKill()) + return false; + MachineInstr *DefMI = li_->getInstructionFromIndex(ValNo->def); + if (!DefMI) + return false; + assert(DefMI && "Defining instruction disappeared"); + const TargetInstrDesc &TID = DefMI->getDesc(); + if (!TID.isAsCheapAsAMove()) + return false; + if (!tii_->isTriviallyReMaterializable(DefMI, AA)) + return false; + bool SawStore = false; + if (!DefMI->isSafeToMove(tii_, AA, SawStore)) + return false; + if (TID.getNumDefs() != 1) + return false; + if (!DefMI->isImplicitDef()) { + // Make sure the copy destination register class fits the instruction + // definition register class. The mismatch can happen as a result of earlier + // extract_subreg, insert_subreg, subreg_to_reg coalescing. + const TargetRegisterClass *RC = TID.OpInfo[0].getRegClass(tri_); + if (TargetRegisterInfo::isVirtualRegister(DstReg)) { + if (mri_->getRegClass(DstReg) != RC) + return false; + } else if (!RC->contains(DstReg)) + return false; + } + + // If destination register has a sub-register index on it, make sure it + // matches the instruction register class. + if (DstSubIdx) { + const TargetInstrDesc &TID = DefMI->getDesc(); + if (TID.getNumDefs() != 1) + return false; + const TargetRegisterClass *DstRC = mri_->getRegClass(DstReg); + const TargetRegisterClass *DstSubRC = + DstRC->getSubRegisterRegClass(DstSubIdx); + const TargetRegisterClass *DefRC = TID.OpInfo[0].getRegClass(tri_); + if (DefRC == DstRC) + DstSubIdx = 0; + else if (DefRC != DstSubRC) + return false; + } + + RemoveCopyFlag(DstReg, CopyMI); + + MachineBasicBlock *MBB = CopyMI->getParent(); + MachineBasicBlock::iterator MII = + llvm::next(MachineBasicBlock::iterator(CopyMI)); + tii_->reMaterialize(*MBB, MII, DstReg, DstSubIdx, DefMI, *tri_); + MachineInstr *NewMI = prior(MII); + + // CopyMI may have implicit operands, transfer them over to the newly + // rematerialized instruction. And update implicit def interval valnos. + for (unsigned i = CopyMI->getDesc().getNumOperands(), + e = CopyMI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = CopyMI->getOperand(i); + if (MO.isReg() && MO.isImplicit()) + NewMI->addOperand(MO); + if (MO.isDef()) + RemoveCopyFlag(MO.getReg(), CopyMI); + } + + NewMI->copyImplicitOps(CopyMI); + li_->ReplaceMachineInstrInMaps(CopyMI, NewMI); + CopyMI->eraseFromParent(); + ReMatCopies.insert(CopyMI); + ReMatDefs.insert(DefMI); + DEBUG(dbgs() << "Remat: " << *NewMI); + ++NumReMats; + + // The source interval can become smaller because we removed a use. + if (preserveSrcInt) + li_->shrinkToUses(&SrcInt); + + return true; +} + +/// UpdateRegDefsUses - Replace all defs and uses of SrcReg to DstReg and +/// update the subregister number if it is not zero. If DstReg is a +/// physical register and the existing subregister number of the def / use +/// being updated is not zero, make sure to set it to the correct physical +/// subregister. +void +SimpleRegisterCoalescing::UpdateRegDefsUses(const CoalescerPair &CP) { + bool DstIsPhys = CP.isPhys(); + unsigned SrcReg = CP.getSrcReg(); + unsigned DstReg = CP.getDstReg(); + unsigned SubIdx = CP.getSubIdx(); + + // Update LiveDebugVariables. + ldv_->renameRegister(SrcReg, DstReg, SubIdx); + + for (MachineRegisterInfo::reg_iterator I = mri_->reg_begin(SrcReg); + MachineInstr *UseMI = I.skipInstruction();) { + // A PhysReg copy that won't be coalesced can perhaps be rematerialized + // instead. + if (DstIsPhys) { + if (UseMI->isCopy() && + !UseMI->getOperand(1).getSubReg() && + !UseMI->getOperand(0).getSubReg() && + UseMI->getOperand(1).getReg() == SrcReg && + UseMI->getOperand(0).getReg() != SrcReg && + UseMI->getOperand(0).getReg() != DstReg && + !JoinedCopies.count(UseMI) && + ReMaterializeTrivialDef(li_->getInterval(SrcReg), false, + UseMI->getOperand(0).getReg(), 0, UseMI)) + continue; + } + + SmallVector Ops; + bool Reads, Writes; + tie(Reads, Writes) = UseMI->readsWritesVirtualRegister(SrcReg, &Ops); + bool Kills = false, Deads = false; + + // Replace SrcReg with DstReg in all UseMI operands. + for (unsigned i = 0, e = Ops.size(); i != e; ++i) { + MachineOperand &MO = UseMI->getOperand(Ops[i]); + Kills |= MO.isKill(); + Deads |= MO.isDead(); + + if (DstIsPhys) + MO.substPhysReg(DstReg, *tri_); + else + MO.substVirtReg(DstReg, SubIdx, *tri_); + } + + // This instruction is a copy that will be removed. + if (JoinedCopies.count(UseMI)) + continue; + + if (SubIdx) { + // If UseMI was a simple SrcReg def, make sure we didn't turn it into a + // read-modify-write of DstReg. + if (Deads) + UseMI->addRegisterDead(DstReg, tri_); + else if (!Reads && Writes) + UseMI->addRegisterDefined(DstReg, tri_); + + // Kill flags apply to the whole physical register. + if (DstIsPhys && Kills) + UseMI->addRegisterKilled(DstReg, tri_); + } + + DEBUG({ + dbgs() << "\t\tupdated: "; + if (!UseMI->isDebugValue()) + dbgs() << li_->getInstructionIndex(UseMI) << "\t"; + dbgs() << *UseMI; + }); + } +} + +/// removeIntervalIfEmpty - Check if the live interval of a physical register +/// is empty, if so remove it and also remove the empty intervals of its +/// sub-registers. Return true if live interval is removed. +static bool removeIntervalIfEmpty(LiveInterval &li, LiveIntervals *li_, + const TargetRegisterInfo *tri_) { + if (li.empty()) { + if (TargetRegisterInfo::isPhysicalRegister(li.reg)) + for (const unsigned* SR = tri_->getSubRegisters(li.reg); *SR; ++SR) { + if (!li_->hasInterval(*SR)) + continue; + LiveInterval &sli = li_->getInterval(*SR); + if (sli.empty()) + li_->removeInterval(*SR); + } + li_->removeInterval(li.reg); + return true; + } + return false; +} + +/// RemoveDeadDef - If a def of a live interval is now determined dead, remove +/// the val# it defines. If the live interval becomes empty, remove it as well. +bool SimpleRegisterCoalescing::RemoveDeadDef(LiveInterval &li, + MachineInstr *DefMI) { + SlotIndex DefIdx = li_->getInstructionIndex(DefMI).getDefIndex(); + LiveInterval::iterator MLR = li.FindLiveRangeContaining(DefIdx); + if (DefIdx != MLR->valno->def) + return false; + li.removeValNo(MLR->valno); + return removeIntervalIfEmpty(li, li_, tri_); +} + +void SimpleRegisterCoalescing::RemoveCopyFlag(unsigned DstReg, + const MachineInstr *CopyMI) { + SlotIndex DefIdx = li_->getInstructionIndex(CopyMI).getDefIndex(); + if (li_->hasInterval(DstReg)) { + LiveInterval &LI = li_->getInterval(DstReg); + if (const LiveRange *LR = LI.getLiveRangeContaining(DefIdx)) + if (LR->valno->def == DefIdx) + LR->valno->setCopy(0); + } + if (!TargetRegisterInfo::isPhysicalRegister(DstReg)) + return; + for (const unsigned* AS = tri_->getAliasSet(DstReg); *AS; ++AS) { + if (!li_->hasInterval(*AS)) + continue; + LiveInterval &LI = li_->getInterval(*AS); + if (const LiveRange *LR = LI.getLiveRangeContaining(DefIdx)) + if (LR->valno->def == DefIdx) + LR->valno->setCopy(0); + } +} + +/// shouldJoinPhys - Return true if a copy involving a physreg should be joined. +/// We need to be careful about coalescing a source physical register with a +/// virtual register. Once the coalescing is done, it cannot be broken and these +/// are not spillable! If the destination interval uses are far away, think +/// twice about coalescing them! +bool SimpleRegisterCoalescing::shouldJoinPhys(CoalescerPair &CP) { + bool Allocatable = li_->isAllocatable(CP.getDstReg()); + LiveInterval &JoinVInt = li_->getInterval(CP.getSrcReg()); + + /// Always join simple intervals that are defined by a single copy from a + /// reserved register. This doesn't increase register pressure, so it is + /// always beneficial. + if (!Allocatable && CP.isFlipped() && JoinVInt.containsOneValue()) + return true; + + if (!EnablePhysicalJoin) { + DEBUG(dbgs() << "\tPhysreg joins disabled.\n"); + return false; + } + + // Only coalesce to allocatable physreg, we don't want to risk modifying + // reserved registers. + if (!Allocatable) { + DEBUG(dbgs() << "\tRegister is an unallocatable physreg.\n"); + return false; // Not coalescable. + } + + // Don't join with physregs that have a ridiculous number of live + // ranges. The data structure performance is really bad when that + // happens. + if (li_->hasInterval(CP.getDstReg()) && + li_->getInterval(CP.getDstReg()).ranges.size() > 1000) { + ++numAborts; + DEBUG(dbgs() + << "\tPhysical register live interval too complicated, abort!\n"); + return false; + } + + // FIXME: Why are we skipping this test for partial copies? + // CodeGen/X86/phys_subreg_coalesce-3.ll needs it. + if (!CP.isPartial()) { + const TargetRegisterClass *RC = mri_->getRegClass(CP.getSrcReg()); + unsigned Threshold = RegClassInfo.getNumAllocatableRegs(RC) * 2; + unsigned Length = li_->getApproximateInstructionCount(JoinVInt); + if (Length > Threshold) { + ++numAborts; + DEBUG(dbgs() << "\tMay tie down a physical register, abort!\n"); + return false; + } + } + return true; +} + +/// isWinToJoinCrossClass - Return true if it's profitable to coalesce +/// two virtual registers from different register classes. +bool +SimpleRegisterCoalescing::isWinToJoinCrossClass(unsigned SrcReg, + unsigned DstReg, + const TargetRegisterClass *SrcRC, + const TargetRegisterClass *DstRC, + const TargetRegisterClass *NewRC) { + unsigned NewRCCount = RegClassInfo.getNumAllocatableRegs(NewRC); + // This heuristics is good enough in practice, but it's obviously not *right*. + // 4 is a magic number that works well enough for x86, ARM, etc. It filter + // out all but the most restrictive register classes. + if (NewRCCount > 4 || + // Early exit if the function is fairly small, coalesce aggressively if + // that's the case. For really special register classes with 3 or + // fewer registers, be a bit more careful. + (li_->getFuncInstructionCount() / NewRCCount) < 8) + return true; + LiveInterval &SrcInt = li_->getInterval(SrcReg); + LiveInterval &DstInt = li_->getInterval(DstReg); + unsigned SrcSize = li_->getApproximateInstructionCount(SrcInt); + unsigned DstSize = li_->getApproximateInstructionCount(DstInt); + + // Coalesce aggressively if the intervals are small compared to the number of + // registers in the new class. The number 4 is fairly arbitrary, chosen to be + // less aggressive than the 8 used for the whole function size. + const unsigned ThresSize = 4 * NewRCCount; + if (SrcSize <= ThresSize && DstSize <= ThresSize) + return true; + + // Estimate *register use density*. If it doubles or more, abort. + unsigned SrcUses = std::distance(mri_->use_nodbg_begin(SrcReg), + mri_->use_nodbg_end()); + unsigned DstUses = std::distance(mri_->use_nodbg_begin(DstReg), + mri_->use_nodbg_end()); + unsigned NewUses = SrcUses + DstUses; + unsigned NewSize = SrcSize + DstSize; + if (SrcRC != NewRC && SrcSize > ThresSize) { + unsigned SrcRCCount = RegClassInfo.getNumAllocatableRegs(SrcRC); + if (NewUses*SrcSize*SrcRCCount > 2*SrcUses*NewSize*NewRCCount) + return false; + } + if (DstRC != NewRC && DstSize > ThresSize) { + unsigned DstRCCount = RegClassInfo.getNumAllocatableRegs(DstRC); + if (NewUses*DstSize*DstRCCount > 2*DstUses*NewSize*NewRCCount) + return false; + } + return true; +} + + +/// JoinCopy - Attempt to join intervals corresponding to SrcReg/DstReg, +/// which are the src/dst of the copy instruction CopyMI. This returns true +/// if the copy was successfully coalesced away. If it is not currently +/// possible to coalesce this interval, but it may be possible if other +/// things get coalesced, then it returns true by reference in 'Again'. +bool SimpleRegisterCoalescing::JoinCopy(MachineInstr *CopyMI, bool &Again) { + + Again = false; + if (JoinedCopies.count(CopyMI) || ReMatCopies.count(CopyMI)) + return false; // Already done. + + DEBUG(dbgs() << li_->getInstructionIndex(CopyMI) << '\t' << *CopyMI); + + CoalescerPair CP(*tii_, *tri_); + if (!CP.setRegisters(CopyMI)) { + DEBUG(dbgs() << "\tNot coalescable.\n"); + return false; + } + + // If they are already joined we continue. + if (CP.getSrcReg() == CP.getDstReg()) { + markAsJoined(CopyMI); + DEBUG(dbgs() << "\tCopy already coalesced.\n"); + return false; // Not coalescable. + } + + DEBUG(dbgs() << "\tConsidering merging " << PrintReg(CP.getSrcReg(), tri_) + << " with " << PrintReg(CP.getDstReg(), tri_, CP.getSubIdx()) + << "\n"); + + // Enforce policies. + if (CP.isPhys()) { + if (!shouldJoinPhys(CP)) { + // Before giving up coalescing, if definition of source is defined by + // trivial computation, try rematerializing it. + if (!CP.isFlipped() && + ReMaterializeTrivialDef(li_->getInterval(CP.getSrcReg()), true, + CP.getDstReg(), 0, CopyMI)) + return true; + return false; + } + } else { + // Avoid constraining virtual register regclass too much. + if (CP.isCrossClass()) { + DEBUG(dbgs() << "\tCross-class to " << CP.getNewRC()->getName() << ".\n"); + if (DisableCrossClassJoin) { + DEBUG(dbgs() << "\tCross-class joins disabled.\n"); + return false; + } + if (!isWinToJoinCrossClass(CP.getSrcReg(), CP.getDstReg(), + mri_->getRegClass(CP.getSrcReg()), + mri_->getRegClass(CP.getDstReg()), + CP.getNewRC())) { + DEBUG(dbgs() << "\tAvoid coalescing to constrained register class.\n"); + Again = true; // May be possible to coalesce later. + return false; + } + } + + // When possible, let DstReg be the larger interval. + if (!CP.getSubIdx() && li_->getInterval(CP.getSrcReg()).ranges.size() > + li_->getInterval(CP.getDstReg()).ranges.size()) + CP.flip(); + } + + // Okay, attempt to join these two intervals. On failure, this returns false. + // Otherwise, if one of the intervals being joined is a physreg, this method + // always canonicalizes DstInt to be it. The output "SrcInt" will not have + // been modified, so we can use this information below to update aliases. + if (!JoinIntervals(CP)) { + // Coalescing failed. + + // If definition of source is defined by trivial computation, try + // rematerializing it. + if (!CP.isFlipped() && + ReMaterializeTrivialDef(li_->getInterval(CP.getSrcReg()), true, + CP.getDstReg(), 0, CopyMI)) + return true; + + // If we can eliminate the copy without merging the live ranges, do so now. + if (!CP.isPartial()) { + if (AdjustCopiesBackFrom(CP, CopyMI) || + RemoveCopyByCommutingDef(CP, CopyMI)) { + markAsJoined(CopyMI); + DEBUG(dbgs() << "\tTrivial!\n"); + return true; + } + } + + // Otherwise, we are unable to join the intervals. + DEBUG(dbgs() << "\tInterference!\n"); + Again = true; // May be possible to coalesce later. + return false; + } + + // Coalescing to a virtual register that is of a sub-register class of the + // other. Make sure the resulting register is set to the right register class. + if (CP.isCrossClass()) { + ++numCrossRCs; + mri_->setRegClass(CP.getDstReg(), CP.getNewRC()); + } + + // Remember to delete the copy instruction. + markAsJoined(CopyMI); + + UpdateRegDefsUses(CP); + + // If we have extended the live range of a physical register, make sure we + // update live-in lists as well. + if (CP.isPhys()) { + SmallVector BlockSeq; + // JoinIntervals invalidates the VNInfos in SrcInt, but we only need the + // ranges for this, and they are preserved. + LiveInterval &SrcInt = li_->getInterval(CP.getSrcReg()); + for (LiveInterval::const_iterator I = SrcInt.begin(), E = SrcInt.end(); + I != E; ++I ) { + li_->findLiveInMBBs(I->start, I->end, BlockSeq); + for (unsigned idx = 0, size = BlockSeq.size(); idx != size; ++idx) { + MachineBasicBlock &block = *BlockSeq[idx]; + if (!block.isLiveIn(CP.getDstReg())) + block.addLiveIn(CP.getDstReg()); + } + BlockSeq.clear(); + } + } + + // SrcReg is guarateed to be the register whose live interval that is + // being merged. + li_->removeInterval(CP.getSrcReg()); + + // Update regalloc hint. + tri_->UpdateRegAllocHint(CP.getSrcReg(), CP.getDstReg(), *mf_); + + DEBUG({ + LiveInterval &DstInt = li_->getInterval(CP.getDstReg()); + dbgs() << "\tJoined. Result = "; + DstInt.print(dbgs(), tri_); + dbgs() << "\n"; + }); + + ++numJoins; + return true; +} + +/// ComputeUltimateVN - Assuming we are going to join two live intervals, +/// compute what the resultant value numbers for each value in the input two +/// ranges will be. This is complicated by copies between the two which can +/// and will commonly cause multiple value numbers to be merged into one. +/// +/// VN is the value number that we're trying to resolve. InstDefiningValue +/// keeps track of the new InstDefiningValue assignment for the result +/// LiveInterval. ThisFromOther/OtherFromThis are sets that keep track of +/// whether a value in this or other is a copy from the opposite set. +/// ThisValNoAssignments/OtherValNoAssignments keep track of value #'s that have +/// already been assigned. +/// +/// ThisFromOther[x] - If x is defined as a copy from the other interval, this +/// contains the value number the copy is from. +/// +static unsigned ComputeUltimateVN(VNInfo *VNI, + SmallVector &NewVNInfo, + DenseMap &ThisFromOther, + DenseMap &OtherFromThis, + SmallVector &ThisValNoAssignments, + SmallVector &OtherValNoAssignments) { + unsigned VN = VNI->id; + + // If the VN has already been computed, just return it. + if (ThisValNoAssignments[VN] >= 0) + return ThisValNoAssignments[VN]; + assert(ThisValNoAssignments[VN] != -2 && "Cyclic value numbers"); + + // If this val is not a copy from the other val, then it must be a new value + // number in the destination. + DenseMap::iterator I = ThisFromOther.find(VNI); + if (I == ThisFromOther.end()) { + NewVNInfo.push_back(VNI); + return ThisValNoAssignments[VN] = NewVNInfo.size()-1; + } + VNInfo *OtherValNo = I->second; + + // Otherwise, this *is* a copy from the RHS. If the other side has already + // been computed, return it. + if (OtherValNoAssignments[OtherValNo->id] >= 0) + return ThisValNoAssignments[VN] = OtherValNoAssignments[OtherValNo->id]; + + // Mark this value number as currently being computed, then ask what the + // ultimate value # of the other value is. + ThisValNoAssignments[VN] = -2; + unsigned UltimateVN = + ComputeUltimateVN(OtherValNo, NewVNInfo, OtherFromThis, ThisFromOther, + OtherValNoAssignments, ThisValNoAssignments); + return ThisValNoAssignments[VN] = UltimateVN; +} + +/// JoinIntervals - Attempt to join these two intervals. On failure, this +/// returns false. +bool SimpleRegisterCoalescing::JoinIntervals(CoalescerPair &CP) { + LiveInterval &RHS = li_->getInterval(CP.getSrcReg()); + DEBUG({ dbgs() << "\t\tRHS = "; RHS.print(dbgs(), tri_); dbgs() << "\n"; }); + + // If a live interval is a physical register, check for interference with any + // aliases. The interference check implemented here is a bit more conservative + // than the full interfeence check below. We allow overlapping live ranges + // only when one is a copy of the other. + if (CP.isPhys()) { + for (const unsigned *AS = tri_->getAliasSet(CP.getDstReg()); *AS; ++AS){ + if (!li_->hasInterval(*AS)) + continue; + const LiveInterval &LHS = li_->getInterval(*AS); + LiveInterval::const_iterator LI = LHS.begin(); + for (LiveInterval::const_iterator RI = RHS.begin(), RE = RHS.end(); + RI != RE; ++RI) { + LI = std::lower_bound(LI, LHS.end(), RI->start); + // Does LHS have an overlapping live range starting before RI? + if ((LI != LHS.begin() && LI[-1].end > RI->start) && + (RI->start != RI->valno->def || + !CP.isCoalescable(li_->getInstructionFromIndex(RI->start)))) { + DEBUG({ + dbgs() << "\t\tInterference from alias: "; + LHS.print(dbgs(), tri_); + dbgs() << "\n\t\tOverlap at " << RI->start << " and no copy.\n"; + }); + return false; + } + + // Check that LHS ranges beginning in this range are copies. + for (; LI != LHS.end() && LI->start < RI->end; ++LI) { + if (LI->start != LI->valno->def || + !CP.isCoalescable(li_->getInstructionFromIndex(LI->start))) { + DEBUG({ + dbgs() << "\t\tInterference from alias: "; + LHS.print(dbgs(), tri_); + dbgs() << "\n\t\tDef at " << LI->start << " is not a copy.\n"; + }); + return false; + } + } + } + } + } + + // Compute the final value assignment, assuming that the live ranges can be + // coalesced. + SmallVector LHSValNoAssignments; + SmallVector RHSValNoAssignments; + DenseMap LHSValsDefinedFromRHS; + DenseMap RHSValsDefinedFromLHS; + SmallVector NewVNInfo; + + LiveInterval &LHS = li_->getOrCreateInterval(CP.getDstReg()); + DEBUG({ dbgs() << "\t\tLHS = "; LHS.print(dbgs(), tri_); dbgs() << "\n"; }); + + // Loop over the value numbers of the LHS, seeing if any are defined from + // the RHS. + for (LiveInterval::vni_iterator i = LHS.vni_begin(), e = LHS.vni_end(); + i != e; ++i) { + VNInfo *VNI = *i; + if (VNI->isUnused() || !VNI->isDefByCopy()) // Src not defined by a copy? + continue; + + // Never join with a register that has EarlyClobber redefs. + if (VNI->hasRedefByEC()) + return false; + + // DstReg is known to be a register in the LHS interval. If the src is + // from the RHS interval, we can use its value #. + if (!CP.isCoalescable(VNI->getCopy())) + continue; + + // Figure out the value # from the RHS. + LiveRange *lr = RHS.getLiveRangeContaining(VNI->def.getPrevSlot()); + // The copy could be to an aliased physreg. + if (!lr) continue; + LHSValsDefinedFromRHS[VNI] = lr->valno; + } + + // Loop over the value numbers of the RHS, seeing if any are defined from + // the LHS. + for (LiveInterval::vni_iterator i = RHS.vni_begin(), e = RHS.vni_end(); + i != e; ++i) { + VNInfo *VNI = *i; + if (VNI->isUnused() || !VNI->isDefByCopy()) // Src not defined by a copy? + continue; + + // Never join with a register that has EarlyClobber redefs. + if (VNI->hasRedefByEC()) + return false; + + // DstReg is known to be a register in the RHS interval. If the src is + // from the LHS interval, we can use its value #. + if (!CP.isCoalescable(VNI->getCopy())) + continue; + + // Figure out the value # from the LHS. + LiveRange *lr = LHS.getLiveRangeContaining(VNI->def.getPrevSlot()); + // The copy could be to an aliased physreg. + if (!lr) continue; + RHSValsDefinedFromLHS[VNI] = lr->valno; + } + + LHSValNoAssignments.resize(LHS.getNumValNums(), -1); + RHSValNoAssignments.resize(RHS.getNumValNums(), -1); + NewVNInfo.reserve(LHS.getNumValNums() + RHS.getNumValNums()); + + for (LiveInterval::vni_iterator i = LHS.vni_begin(), e = LHS.vni_end(); + i != e; ++i) { + VNInfo *VNI = *i; + unsigned VN = VNI->id; + if (LHSValNoAssignments[VN] >= 0 || VNI->isUnused()) + continue; + ComputeUltimateVN(VNI, NewVNInfo, + LHSValsDefinedFromRHS, RHSValsDefinedFromLHS, + LHSValNoAssignments, RHSValNoAssignments); + } + for (LiveInterval::vni_iterator i = RHS.vni_begin(), e = RHS.vni_end(); + i != e; ++i) { + VNInfo *VNI = *i; + unsigned VN = VNI->id; + if (RHSValNoAssignments[VN] >= 0 || VNI->isUnused()) + continue; + // If this value number isn't a copy from the LHS, it's a new number. + if (RHSValsDefinedFromLHS.find(VNI) == RHSValsDefinedFromLHS.end()) { + NewVNInfo.push_back(VNI); + RHSValNoAssignments[VN] = NewVNInfo.size()-1; + continue; + } + + ComputeUltimateVN(VNI, NewVNInfo, + RHSValsDefinedFromLHS, LHSValsDefinedFromRHS, + RHSValNoAssignments, LHSValNoAssignments); + } + + // Armed with the mappings of LHS/RHS values to ultimate values, walk the + // interval lists to see if these intervals are coalescable. + LiveInterval::const_iterator I = LHS.begin(); + LiveInterval::const_iterator IE = LHS.end(); + LiveInterval::const_iterator J = RHS.begin(); + LiveInterval::const_iterator JE = RHS.end(); + + // Skip ahead until the first place of potential sharing. + if (I != IE && J != JE) { + if (I->start < J->start) { + I = std::upper_bound(I, IE, J->start); + if (I != LHS.begin()) --I; + } else if (J->start < I->start) { + J = std::upper_bound(J, JE, I->start); + if (J != RHS.begin()) --J; + } + } + + while (I != IE && J != JE) { + // Determine if these two live ranges overlap. + bool Overlaps; + if (I->start < J->start) { + Overlaps = I->end > J->start; + } else { + Overlaps = J->end > I->start; + } + + // If so, check value # info to determine if they are really different. + if (Overlaps) { + // If the live range overlap will map to the same value number in the + // result liverange, we can still coalesce them. If not, we can't. + if (LHSValNoAssignments[I->valno->id] != + RHSValNoAssignments[J->valno->id]) + return false; + // If it's re-defined by an early clobber somewhere in the live range, + // then conservatively abort coalescing. + if (NewVNInfo[LHSValNoAssignments[I->valno->id]]->hasRedefByEC()) + return false; + } + + if (I->end < J->end) + ++I; + else + ++J; + } + + // Update kill info. Some live ranges are extended due to copy coalescing. + for (DenseMap::iterator I = LHSValsDefinedFromRHS.begin(), + E = LHSValsDefinedFromRHS.end(); I != E; ++I) { + VNInfo *VNI = I->first; + unsigned LHSValID = LHSValNoAssignments[VNI->id]; + if (VNI->hasPHIKill()) + NewVNInfo[LHSValID]->setHasPHIKill(true); + } + + // Update kill info. Some live ranges are extended due to copy coalescing. + for (DenseMap::iterator I = RHSValsDefinedFromLHS.begin(), + E = RHSValsDefinedFromLHS.end(); I != E; ++I) { + VNInfo *VNI = I->first; + unsigned RHSValID = RHSValNoAssignments[VNI->id]; + if (VNI->hasPHIKill()) + NewVNInfo[RHSValID]->setHasPHIKill(true); + } + + if (LHSValNoAssignments.empty()) + LHSValNoAssignments.push_back(-1); + if (RHSValNoAssignments.empty()) + RHSValNoAssignments.push_back(-1); + + // If we get here, we know that we can coalesce the live ranges. Ask the + // intervals to coalesce themselves now. + LHS.join(RHS, &LHSValNoAssignments[0], &RHSValNoAssignments[0], NewVNInfo, + mri_); + return true; +} + +namespace { + // DepthMBBCompare - Comparison predicate that sort first based on the loop + // depth of the basic block (the unsigned), and then on the MBB number. + struct DepthMBBCompare { + typedef std::pair DepthMBBPair; + bool operator()(const DepthMBBPair &LHS, const DepthMBBPair &RHS) const { + // Deeper loops first + if (LHS.first != RHS.first) + return LHS.first > RHS.first; + + // Prefer blocks that are more connected in the CFG. This takes care of + // the most difficult copies first while intervals are short. + unsigned cl = LHS.second->pred_size() + LHS.second->succ_size(); + unsigned cr = RHS.second->pred_size() + RHS.second->succ_size(); + if (cl != cr) + return cl > cr; + + // As a last resort, sort by block number. + return LHS.second->getNumber() < RHS.second->getNumber(); + } + }; +} + +void SimpleRegisterCoalescing::CopyCoalesceInMBB(MachineBasicBlock *MBB, + std::vector &TryAgain) { + DEBUG(dbgs() << MBB->getName() << ":\n"); + + SmallVector VirtCopies; + SmallVector PhysCopies; + SmallVector ImpDefCopies; + for (MachineBasicBlock::iterator MII = MBB->begin(), E = MBB->end(); + MII != E;) { + MachineInstr *Inst = MII++; + + // If this isn't a copy nor a extract_subreg, we can't join intervals. + unsigned SrcReg, DstReg; + if (Inst->isCopy()) { + DstReg = Inst->getOperand(0).getReg(); + SrcReg = Inst->getOperand(1).getReg(); + } else if (Inst->isSubregToReg()) { + DstReg = Inst->getOperand(0).getReg(); + SrcReg = Inst->getOperand(2).getReg(); + } else + continue; + + bool SrcIsPhys = TargetRegisterInfo::isPhysicalRegister(SrcReg); + bool DstIsPhys = TargetRegisterInfo::isPhysicalRegister(DstReg); + if (li_->hasInterval(SrcReg) && li_->getInterval(SrcReg).empty()) + ImpDefCopies.push_back(Inst); + else if (SrcIsPhys || DstIsPhys) + PhysCopies.push_back(Inst); + else + VirtCopies.push_back(Inst); + } + + // Try coalescing implicit copies and insert_subreg first, + // followed by copies to / from physical registers, then finally copies + // from virtual registers to virtual registers. + for (unsigned i = 0, e = ImpDefCopies.size(); i != e; ++i) { + MachineInstr *TheCopy = ImpDefCopies[i]; + bool Again = false; + if (!JoinCopy(TheCopy, Again)) + if (Again) + TryAgain.push_back(TheCopy); + } + for (unsigned i = 0, e = PhysCopies.size(); i != e; ++i) { + MachineInstr *TheCopy = PhysCopies[i]; + bool Again = false; + if (!JoinCopy(TheCopy, Again)) + if (Again) + TryAgain.push_back(TheCopy); + } + for (unsigned i = 0, e = VirtCopies.size(); i != e; ++i) { + MachineInstr *TheCopy = VirtCopies[i]; + bool Again = false; + if (!JoinCopy(TheCopy, Again)) + if (Again) + TryAgain.push_back(TheCopy); + } +} + +void SimpleRegisterCoalescing::joinIntervals() { + DEBUG(dbgs() << "********** JOINING INTERVALS ***********\n"); + + std::vector TryAgainList; + if (loopInfo->empty()) { + // If there are no loops in the function, join intervals in function order. + for (MachineFunction::iterator I = mf_->begin(), E = mf_->end(); + I != E; ++I) + CopyCoalesceInMBB(I, TryAgainList); + } else { + // Otherwise, join intervals in inner loops before other intervals. + // Unfortunately we can't just iterate over loop hierarchy here because + // there may be more MBB's than BB's. Collect MBB's for sorting. + + // Join intervals in the function prolog first. We want to join physical + // registers with virtual registers before the intervals got too long. + std::vector > MBBs; + for (MachineFunction::iterator I = mf_->begin(), E = mf_->end();I != E;++I){ + MachineBasicBlock *MBB = I; + MBBs.push_back(std::make_pair(loopInfo->getLoopDepth(MBB), I)); + } + + // Sort by loop depth. + std::sort(MBBs.begin(), MBBs.end(), DepthMBBCompare()); + + // Finally, join intervals in loop nest order. + for (unsigned i = 0, e = MBBs.size(); i != e; ++i) + CopyCoalesceInMBB(MBBs[i].second, TryAgainList); + } + + // Joining intervals can allow other intervals to be joined. Iteratively join + // until we make no progress. + bool ProgressMade = true; + while (ProgressMade) { + ProgressMade = false; + + for (unsigned i = 0, e = TryAgainList.size(); i != e; ++i) { + MachineInstr *&TheCopy = TryAgainList[i]; + if (!TheCopy) + continue; + + bool Again = false; + bool Success = JoinCopy(TheCopy, Again); + if (Success || !Again) { + TheCopy= 0; // Mark this one as done. + ProgressMade = true; + } + } + } +} + +void SimpleRegisterCoalescing::releaseMemory() { + JoinedCopies.clear(); + ReMatCopies.clear(); + ReMatDefs.clear(); +} + +bool SimpleRegisterCoalescing::runOnMachineFunction(MachineFunction &fn) { + mf_ = &fn; + mri_ = &fn.getRegInfo(); + tm_ = &fn.getTarget(); + tri_ = tm_->getRegisterInfo(); + tii_ = tm_->getInstrInfo(); + li_ = &getAnalysis(); + ldv_ = &getAnalysis(); + AA = &getAnalysis(); + loopInfo = &getAnalysis(); + + DEBUG(dbgs() << "********** SIMPLE REGISTER COALESCING **********\n" + << "********** Function: " + << ((Value*)mf_->getFunction())->getName() << '\n'); + + if (VerifyCoalescing) + mf_->verify(this, "Before register coalescing"); + + RegClassInfo.runOnMachineFunction(fn); + + // Join (coalesce) intervals if requested. + if (EnableJoining) { + joinIntervals(); + DEBUG({ + dbgs() << "********** INTERVALS POST JOINING **********\n"; + for (LiveIntervals::iterator I = li_->begin(), E = li_->end(); + I != E; ++I){ + I->second->print(dbgs(), tri_); + dbgs() << "\n"; + } + }); + } + + // Perform a final pass over the instructions and compute spill weights + // and remove identity moves. + SmallVector DeadDefs; + for (MachineFunction::iterator mbbi = mf_->begin(), mbbe = mf_->end(); + mbbi != mbbe; ++mbbi) { + MachineBasicBlock* mbb = mbbi; + for (MachineBasicBlock::iterator mii = mbb->begin(), mie = mbb->end(); + mii != mie; ) { + MachineInstr *MI = mii; + if (JoinedCopies.count(MI)) { + // Delete all coalesced copies. + bool DoDelete = true; + assert(MI->isCopyLike() && "Unrecognized copy instruction"); + unsigned SrcReg = MI->getOperand(MI->isSubregToReg() ? 2 : 1).getReg(); + if (TargetRegisterInfo::isPhysicalRegister(SrcReg) && + MI->getNumOperands() > 2) + // Do not delete extract_subreg, insert_subreg of physical + // registers unless the definition is dead. e.g. + // %DO = INSERT_SUBREG %D0, %S0, 1 + // or else the scavenger may complain. LowerSubregs will + // delete them later. + DoDelete = false; + + if (MI->allDefsAreDead()) { + if (TargetRegisterInfo::isVirtualRegister(SrcReg) && + li_->hasInterval(SrcReg)) + li_->shrinkToUses(&li_->getInterval(SrcReg)); + DoDelete = true; + } + if (!DoDelete) { + // We need the instruction to adjust liveness, so make it a KILL. + if (MI->isSubregToReg()) { + MI->RemoveOperand(3); + MI->RemoveOperand(1); + } + MI->setDesc(tii_->get(TargetOpcode::KILL)); + mii = llvm::next(mii); + } else { + li_->RemoveMachineInstrFromMaps(MI); + mii = mbbi->erase(mii); + ++numPeep; + } + continue; + } + + // Now check if this is a remat'ed def instruction which is now dead. + if (ReMatDefs.count(MI)) { + bool isDead = true; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg()) + continue; + unsigned Reg = MO.getReg(); + if (!Reg) + continue; + if (TargetRegisterInfo::isVirtualRegister(Reg)) + DeadDefs.push_back(Reg); + if (MO.isDead()) + continue; + if (TargetRegisterInfo::isPhysicalRegister(Reg) || + !mri_->use_nodbg_empty(Reg)) { + isDead = false; + break; + } + } + if (isDead) { + while (!DeadDefs.empty()) { + unsigned DeadDef = DeadDefs.back(); + DeadDefs.pop_back(); + RemoveDeadDef(li_->getInterval(DeadDef), MI); + } + li_->RemoveMachineInstrFromMaps(mii); + mii = mbbi->erase(mii); + continue; + } else + DeadDefs.clear(); + } + + ++mii; + + // Check for now unnecessary kill flags. + if (li_->isNotInMIMap(MI)) continue; + SlotIndex DefIdx = li_->getInstructionIndex(MI).getDefIndex(); + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || !MO.isKill()) continue; + unsigned reg = MO.getReg(); + if (!reg || !li_->hasInterval(reg)) continue; + if (!li_->getInterval(reg).killedAt(DefIdx)) { + MO.setIsKill(false); + continue; + } + // When leaving a kill flag on a physreg, check if any subregs should + // remain alive. + if (!TargetRegisterInfo::isPhysicalRegister(reg)) + continue; + for (const unsigned *SR = tri_->getSubRegisters(reg); + unsigned S = *SR; ++SR) + if (li_->hasInterval(S) && li_->getInterval(S).liveAt(DefIdx)) + MI->addRegisterDefined(S, tri_); + } + } + } + + DEBUG(dump()); + DEBUG(ldv_->dump()); + if (VerifyCoalescing) + mf_->verify(this, "After register coalescing"); + return true; +} + +/// print - Implement the dump method. +void SimpleRegisterCoalescing::print(raw_ostream &O, const Module* m) const { + li_->print(O, m); +} + +RegisterCoalescer* llvm::createSimpleRegisterCoalescer() { + return new SimpleRegisterCoalescing(); +} + +// Make sure that anything that uses RegisterCoalescer pulls in this file... +DEFINING_FILE_FOR(SimpleRegisterCoalescing) diff --git a/lib/CodeGen/SimpleRegisterCoalescing.cpp b/lib/CodeGen/SimpleRegisterCoalescing.cpp deleted file mode 100644 index 8283965..0000000 --- a/lib/CodeGen/SimpleRegisterCoalescing.cpp +++ /dev/null @@ -1,1538 +0,0 @@ -//===-- SimpleRegisterCoalescing.cpp - Register Coalescing ----------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements a simple register coalescing pass that attempts to -// aggressively coalesce every register copy that it can. -// -//===----------------------------------------------------------------------===// - -#define DEBUG_TYPE "regcoalescing" -#include "RegisterCoalescer.h" -#include "VirtRegMap.h" -#include "LiveDebugVariables.h" -#include "RegisterCoalescer.h" -#include "llvm/CodeGen/LiveIntervalAnalysis.h" -#include "llvm/Value.h" -#include "llvm/Analysis/AliasAnalysis.h" -#include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/CodeGen/MachineLoopInfo.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/Passes.h" -#include "llvm/Target/TargetInstrInfo.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetOptions.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/ADT/OwningPtr.h" -#include "llvm/ADT/SmallSet.h" -#include "llvm/ADT/Statistic.h" -#include "llvm/ADT/STLExtras.h" -#include -#include -using namespace llvm; - -STATISTIC(numJoins , "Number of interval joins performed"); -STATISTIC(numCrossRCs , "Number of cross class joins performed"); -STATISTIC(numCommutes , "Number of instruction commuting performed"); -STATISTIC(numExtends , "Number of copies extended"); -STATISTIC(NumReMats , "Number of instructions re-materialized"); -STATISTIC(numPeep , "Number of identity moves eliminated after coalescing"); -STATISTIC(numAborts , "Number of times interval joining aborted"); - -char SimpleRegisterCoalescing::ID = 0; -static cl::opt -EnableJoining("join-liveintervals", - cl::desc("Coalesce copies (default=true)"), - cl::init(true)); - -static cl::opt -DisableCrossClassJoin("disable-cross-class-join", - cl::desc("Avoid coalescing cross register class copies"), - cl::init(false), cl::Hidden); - -static cl::opt -EnablePhysicalJoin("join-physregs", - cl::desc("Join physical register copies"), - cl::init(false), cl::Hidden); - -static cl::opt -VerifyCoalescing("verify-coalescing", - cl::desc("Verify machine instrs before and after register coalescing"), - cl::Hidden); - -INITIALIZE_AG_PASS_BEGIN(SimpleRegisterCoalescing, RegisterCoalescer, - "simple-register-coalescing", "Simple Register Coalescing", - false, false, true) -INITIALIZE_PASS_DEPENDENCY(LiveIntervals) -INITIALIZE_PASS_DEPENDENCY(LiveDebugVariables) -INITIALIZE_PASS_DEPENDENCY(SlotIndexes) -INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo) -INITIALIZE_PASS_DEPENDENCY(StrongPHIElimination) -INITIALIZE_PASS_DEPENDENCY(PHIElimination) -INITIALIZE_PASS_DEPENDENCY(TwoAddressInstructionPass) -INITIALIZE_AG_DEPENDENCY(AliasAnalysis) -INITIALIZE_AG_PASS_END(SimpleRegisterCoalescing, RegisterCoalescer, - "simple-register-coalescing", "Simple Register Coalescing", - false, false, true) - -char &llvm::SimpleRegisterCoalescingID = SimpleRegisterCoalescing::ID; - -void SimpleRegisterCoalescing::getAnalysisUsage(AnalysisUsage &AU) const { - AU.setPreservesCFG(); - AU.addRequired(); - AU.addRequired(); - AU.addPreserved(); - AU.addRequired(); - AU.addPreserved(); - AU.addPreserved(); - AU.addRequired(); - AU.addPreserved(); - AU.addPreservedID(MachineDominatorsID); - AU.addPreservedID(StrongPHIEliminationID); - AU.addPreservedID(PHIEliminationID); - AU.addPreservedID(TwoAddressInstructionPassID); - MachineFunctionPass::getAnalysisUsage(AU); -} - -void SimpleRegisterCoalescing::markAsJoined(MachineInstr *CopyMI) { - /// Joined copies are not deleted immediately, but kept in JoinedCopies. - JoinedCopies.insert(CopyMI); - - /// Mark all register operands of CopyMI as so they won't affect dead - /// code elimination. - for (MachineInstr::mop_iterator I = CopyMI->operands_begin(), - E = CopyMI->operands_end(); I != E; ++I) - if (I->isReg()) - I->setIsUndef(true); -} - -/// AdjustCopiesBackFrom - We found a non-trivially-coalescable copy with IntA -/// being the source and IntB being the dest, thus this defines a value number -/// in IntB. If the source value number (in IntA) is defined by a copy from B, -/// see if we can merge these two pieces of B into a single value number, -/// eliminating a copy. For example: -/// -/// A3 = B0 -/// ... -/// B1 = A3 <- this copy -/// -/// In this case, B0 can be extended to where the B1 copy lives, allowing the B1 -/// value number to be replaced with B0 (which simplifies the B liveinterval). -/// -/// This returns true if an interval was modified. -/// -bool SimpleRegisterCoalescing::AdjustCopiesBackFrom(const CoalescerPair &CP, - MachineInstr *CopyMI) { - // Bail if there is no dst interval - can happen when merging physical subreg - // operations. - if (!li_->hasInterval(CP.getDstReg())) - return false; - - LiveInterval &IntA = - li_->getInterval(CP.isFlipped() ? CP.getDstReg() : CP.getSrcReg()); - LiveInterval &IntB = - li_->getInterval(CP.isFlipped() ? CP.getSrcReg() : CP.getDstReg()); - SlotIndex CopyIdx = li_->getInstructionIndex(CopyMI).getDefIndex(); - - // BValNo is a value number in B that is defined by a copy from A. 'B3' in - // the example above. - LiveInterval::iterator BLR = IntB.FindLiveRangeContaining(CopyIdx); - if (BLR == IntB.end()) return false; - VNInfo *BValNo = BLR->valno; - - // Get the location that B is defined at. Two options: either this value has - // an unknown definition point or it is defined at CopyIdx. If unknown, we - // can't process it. - if (!BValNo->isDefByCopy()) return false; - assert(BValNo->def == CopyIdx && "Copy doesn't define the value?"); - - // AValNo is the value number in A that defines the copy, A3 in the example. - SlotIndex CopyUseIdx = CopyIdx.getUseIndex(); - LiveInterval::iterator ALR = IntA.FindLiveRangeContaining(CopyUseIdx); - // The live range might not exist after fun with physreg coalescing. - if (ALR == IntA.end()) return false; - VNInfo *AValNo = ALR->valno; - // If it's re-defined by an early clobber somewhere in the live range, then - // it's not safe to eliminate the copy. FIXME: This is a temporary workaround. - // See PR3149: - // 172 %ECX = MOV32rr %reg1039 - // 180 INLINEASM , 10, %EAX, 14, %ECX, 9, - // %EAX, - // 36, , 1, %reg0, 0, 9, %ECX, 36, , 1, %reg0, 0 - // 188 %EAX = MOV32rr %EAX - // 196 %ECX = MOV32rr %ECX - // 204 %ECX = MOV32rr %ECX - // 212 %EAX = MOV32rr %EAX - // 220 %EAX = MOV32rr %EAX - // 228 %reg1039 = MOV32rr %ECX - // The early clobber operand ties ECX input to the ECX def. - // - // The live interval of ECX is represented as this: - // %reg20,inf = [46,47:1)[174,230:0) 0@174-(230) 1@46-(47) - // The coalescer has no idea there was a def in the middle of [174,230]. - if (AValNo->hasRedefByEC()) - return false; - - // If AValNo is defined as a copy from IntB, we can potentially process this. - // Get the instruction that defines this value number. - if (!CP.isCoalescable(AValNo->getCopy())) - return false; - - // Get the LiveRange in IntB that this value number starts with. - LiveInterval::iterator ValLR = - IntB.FindLiveRangeContaining(AValNo->def.getPrevSlot()); - if (ValLR == IntB.end()) - return false; - - // Make sure that the end of the live range is inside the same block as - // CopyMI. - MachineInstr *ValLREndInst = - li_->getInstructionFromIndex(ValLR->end.getPrevSlot()); - if (!ValLREndInst || ValLREndInst->getParent() != CopyMI->getParent()) - return false; - - // Okay, we now know that ValLR ends in the same block that the CopyMI - // live-range starts. If there are no intervening live ranges between them in - // IntB, we can merge them. - if (ValLR+1 != BLR) return false; - - // If a live interval is a physical register, conservatively check if any - // of its aliases is overlapping the live interval of the virtual register. - // If so, do not coalesce. - if (TargetRegisterInfo::isPhysicalRegister(IntB.reg)) { - for (const unsigned *AS = tri_->getAliasSet(IntB.reg); *AS; ++AS) - if (li_->hasInterval(*AS) && IntA.overlaps(li_->getInterval(*AS))) { - DEBUG({ - dbgs() << "\t\tInterfere with alias "; - li_->getInterval(*AS).print(dbgs(), tri_); - }); - return false; - } - } - - DEBUG({ - dbgs() << "Extending: "; - IntB.print(dbgs(), tri_); - }); - - SlotIndex FillerStart = ValLR->end, FillerEnd = BLR->start; - // We are about to delete CopyMI, so need to remove it as the 'instruction - // that defines this value #'. Update the valnum with the new defining - // instruction #. - BValNo->def = FillerStart; - BValNo->setCopy(0); - - // Okay, we can merge them. We need to insert a new liverange: - // [ValLR.end, BLR.begin) of either value number, then we merge the - // two value numbers. - IntB.addRange(LiveRange(FillerStart, FillerEnd, BValNo)); - - // If the IntB live range is assigned to a physical register, and if that - // physreg has sub-registers, update their live intervals as well. - if (TargetRegisterInfo::isPhysicalRegister(IntB.reg)) { - for (const unsigned *SR = tri_->getSubRegisters(IntB.reg); *SR; ++SR) { - if (!li_->hasInterval(*SR)) - continue; - LiveInterval &SRLI = li_->getInterval(*SR); - SRLI.addRange(LiveRange(FillerStart, FillerEnd, - SRLI.getNextValue(FillerStart, 0, - li_->getVNInfoAllocator()))); - } - } - - // Okay, merge "B1" into the same value number as "B0". - if (BValNo != ValLR->valno) { - // If B1 is killed by a PHI, then the merged live range must also be killed - // by the same PHI, as B0 and B1 can not overlap. - bool HasPHIKill = BValNo->hasPHIKill(); - IntB.MergeValueNumberInto(BValNo, ValLR->valno); - if (HasPHIKill) - ValLR->valno->setHasPHIKill(true); - } - DEBUG({ - dbgs() << " result = "; - IntB.print(dbgs(), tri_); - dbgs() << "\n"; - }); - - // If the source instruction was killing the source register before the - // merge, unset the isKill marker given the live range has been extended. - int UIdx = ValLREndInst->findRegisterUseOperandIdx(IntB.reg, true); - if (UIdx != -1) { - ValLREndInst->getOperand(UIdx).setIsKill(false); - } - - // If the copy instruction was killing the destination register before the - // merge, find the last use and trim the live range. That will also add the - // isKill marker. - if (ALR->end == CopyIdx) - li_->shrinkToUses(&IntA); - - ++numExtends; - return true; -} - -/// HasOtherReachingDefs - Return true if there are definitions of IntB -/// other than BValNo val# that can reach uses of AValno val# of IntA. -bool SimpleRegisterCoalescing::HasOtherReachingDefs(LiveInterval &IntA, - LiveInterval &IntB, - VNInfo *AValNo, - VNInfo *BValNo) { - for (LiveInterval::iterator AI = IntA.begin(), AE = IntA.end(); - AI != AE; ++AI) { - if (AI->valno != AValNo) continue; - LiveInterval::Ranges::iterator BI = - std::upper_bound(IntB.ranges.begin(), IntB.ranges.end(), AI->start); - if (BI != IntB.ranges.begin()) - --BI; - for (; BI != IntB.ranges.end() && AI->end >= BI->start; ++BI) { - if (BI->valno == BValNo) - continue; - if (BI->start <= AI->start && BI->end > AI->start) - return true; - if (BI->start > AI->start && BI->start < AI->end) - return true; - } - } - return false; -} - -/// RemoveCopyByCommutingDef - We found a non-trivially-coalescable copy with -/// IntA being the source and IntB being the dest, thus this defines a value -/// number in IntB. If the source value number (in IntA) is defined by a -/// commutable instruction and its other operand is coalesced to the copy dest -/// register, see if we can transform the copy into a noop by commuting the -/// definition. For example, -/// -/// A3 = op A2 B0 -/// ... -/// B1 = A3 <- this copy -/// ... -/// = op A3 <- more uses -/// -/// ==> -/// -/// B2 = op B0 A2 -/// ... -/// B1 = B2 <- now an identify copy -/// ... -/// = op B2 <- more uses -/// -/// This returns true if an interval was modified. -/// -bool SimpleRegisterCoalescing::RemoveCopyByCommutingDef(const CoalescerPair &CP, - MachineInstr *CopyMI) { - // FIXME: For now, only eliminate the copy by commuting its def when the - // source register is a virtual register. We want to guard against cases - // where the copy is a back edge copy and commuting the def lengthen the - // live interval of the source register to the entire loop. - if (CP.isPhys() && CP.isFlipped()) - return false; - - // Bail if there is no dst interval. - if (!li_->hasInterval(CP.getDstReg())) - return false; - - SlotIndex CopyIdx = li_->getInstructionIndex(CopyMI).getDefIndex(); - - LiveInterval &IntA = - li_->getInterval(CP.isFlipped() ? CP.getDstReg() : CP.getSrcReg()); - LiveInterval &IntB = - li_->getInterval(CP.isFlipped() ? CP.getSrcReg() : CP.getDstReg()); - - // BValNo is a value number in B that is defined by a copy from A. 'B3' in - // the example above. - VNInfo *BValNo = IntB.getVNInfoAt(CopyIdx); - if (!BValNo || !BValNo->isDefByCopy()) - return false; - - assert(BValNo->def == CopyIdx && "Copy doesn't define the value?"); - - // AValNo is the value number in A that defines the copy, A3 in the example. - VNInfo *AValNo = IntA.getVNInfoAt(CopyIdx.getUseIndex()); - assert(AValNo && "COPY source not live"); - - // If other defs can reach uses of this def, then it's not safe to perform - // the optimization. - if (AValNo->isPHIDef() || AValNo->isUnused() || AValNo->hasPHIKill()) - return false; - MachineInstr *DefMI = li_->getInstructionFromIndex(AValNo->def); - if (!DefMI) - return false; - const TargetInstrDesc &TID = DefMI->getDesc(); - if (!TID.isCommutable()) - return false; - // If DefMI is a two-address instruction then commuting it will change the - // destination register. - int DefIdx = DefMI->findRegisterDefOperandIdx(IntA.reg); - assert(DefIdx != -1); - unsigned UseOpIdx; - if (!DefMI->isRegTiedToUseOperand(DefIdx, &UseOpIdx)) - return false; - unsigned Op1, Op2, NewDstIdx; - if (!tii_->findCommutedOpIndices(DefMI, Op1, Op2)) - return false; - if (Op1 == UseOpIdx) - NewDstIdx = Op2; - else if (Op2 == UseOpIdx) - NewDstIdx = Op1; - else - return false; - - MachineOperand &NewDstMO = DefMI->getOperand(NewDstIdx); - unsigned NewReg = NewDstMO.getReg(); - if (NewReg != IntB.reg || !NewDstMO.isKill()) - return false; - - // Make sure there are no other definitions of IntB that would reach the - // uses which the new definition can reach. - if (HasOtherReachingDefs(IntA, IntB, AValNo, BValNo)) - return false; - - // Abort if the aliases of IntB.reg have values that are not simply the - // clobbers from the superreg. - if (TargetRegisterInfo::isPhysicalRegister(IntB.reg)) - for (const unsigned *AS = tri_->getAliasSet(IntB.reg); *AS; ++AS) - if (li_->hasInterval(*AS) && - HasOtherReachingDefs(IntA, li_->getInterval(*AS), AValNo, 0)) - return false; - - // If some of the uses of IntA.reg is already coalesced away, return false. - // It's not possible to determine whether it's safe to perform the coalescing. - for (MachineRegisterInfo::use_nodbg_iterator UI = - mri_->use_nodbg_begin(IntA.reg), - UE = mri_->use_nodbg_end(); UI != UE; ++UI) { - MachineInstr *UseMI = &*UI; - SlotIndex UseIdx = li_->getInstructionIndex(UseMI); - LiveInterval::iterator ULR = IntA.FindLiveRangeContaining(UseIdx); - if (ULR == IntA.end()) - continue; - if (ULR->valno == AValNo && JoinedCopies.count(UseMI)) - return false; - } - - DEBUG(dbgs() << "\tRemoveCopyByCommutingDef: " << AValNo->def << '\t' - << *DefMI); - - // At this point we have decided that it is legal to do this - // transformation. Start by commuting the instruction. - MachineBasicBlock *MBB = DefMI->getParent(); - MachineInstr *NewMI = tii_->commuteInstruction(DefMI); - if (!NewMI) - return false; - if (TargetRegisterInfo::isVirtualRegister(IntA.reg) && - TargetRegisterInfo::isVirtualRegister(IntB.reg) && - !mri_->constrainRegClass(IntB.reg, mri_->getRegClass(IntA.reg))) - return false; - if (NewMI != DefMI) { - li_->ReplaceMachineInstrInMaps(DefMI, NewMI); - MBB->insert(DefMI, NewMI); - MBB->erase(DefMI); - } - unsigned OpIdx = NewMI->findRegisterUseOperandIdx(IntA.reg, false); - NewMI->getOperand(OpIdx).setIsKill(); - - // If ALR and BLR overlaps and end of BLR extends beyond end of ALR, e.g. - // A = or A, B - // ... - // B = A - // ... - // C = A - // ... - // = B - - // Update uses of IntA of the specific Val# with IntB. - for (MachineRegisterInfo::use_iterator UI = mri_->use_begin(IntA.reg), - UE = mri_->use_end(); UI != UE;) { - MachineOperand &UseMO = UI.getOperand(); - MachineInstr *UseMI = &*UI; - ++UI; - if (JoinedCopies.count(UseMI)) - continue; - if (UseMI->isDebugValue()) { - // FIXME These don't have an instruction index. Not clear we have enough - // info to decide whether to do this replacement or not. For now do it. - UseMO.setReg(NewReg); - continue; - } - SlotIndex UseIdx = li_->getInstructionIndex(UseMI).getUseIndex(); - LiveInterval::iterator ULR = IntA.FindLiveRangeContaining(UseIdx); - if (ULR == IntA.end() || ULR->valno != AValNo) - continue; - if (TargetRegisterInfo::isPhysicalRegister(NewReg)) - UseMO.substPhysReg(NewReg, *tri_); - else - UseMO.setReg(NewReg); - if (UseMI == CopyMI) - continue; - if (!UseMI->isCopy()) - continue; - if (UseMI->getOperand(0).getReg() != IntB.reg || - UseMI->getOperand(0).getSubReg()) - continue; - - // This copy will become a noop. If it's defining a new val#, merge it into - // BValNo. - SlotIndex DefIdx = UseIdx.getDefIndex(); - VNInfo *DVNI = IntB.getVNInfoAt(DefIdx); - if (!DVNI) - continue; - DEBUG(dbgs() << "\t\tnoop: " << DefIdx << '\t' << *UseMI); - assert(DVNI->def == DefIdx); - BValNo = IntB.MergeValueNumberInto(BValNo, DVNI); - markAsJoined(UseMI); - } - - // Extend BValNo by merging in IntA live ranges of AValNo. Val# definition - // is updated. - VNInfo *ValNo = BValNo; - ValNo->def = AValNo->def; - ValNo->setCopy(0); - for (LiveInterval::iterator AI = IntA.begin(), AE = IntA.end(); - AI != AE; ++AI) { - if (AI->valno != AValNo) continue; - IntB.addRange(LiveRange(AI->start, AI->end, ValNo)); - } - DEBUG(dbgs() << "\t\textended: " << IntB << '\n'); - - IntA.removeValNo(AValNo); - DEBUG(dbgs() << "\t\ttrimmed: " << IntA << '\n'); - ++numCommutes; - return true; -} - -/// ReMaterializeTrivialDef - If the source of a copy is defined by a trivial -/// computation, replace the copy by rematerialize the definition. -bool SimpleRegisterCoalescing::ReMaterializeTrivialDef(LiveInterval &SrcInt, - bool preserveSrcInt, - unsigned DstReg, - unsigned DstSubIdx, - MachineInstr *CopyMI) { - SlotIndex CopyIdx = li_->getInstructionIndex(CopyMI).getUseIndex(); - LiveInterval::iterator SrcLR = SrcInt.FindLiveRangeContaining(CopyIdx); - assert(SrcLR != SrcInt.end() && "Live range not found!"); - VNInfo *ValNo = SrcLR->valno; - // If other defs can reach uses of this def, then it's not safe to perform - // the optimization. - if (ValNo->isPHIDef() || ValNo->isUnused() || ValNo->hasPHIKill()) - return false; - MachineInstr *DefMI = li_->getInstructionFromIndex(ValNo->def); - if (!DefMI) - return false; - assert(DefMI && "Defining instruction disappeared"); - const TargetInstrDesc &TID = DefMI->getDesc(); - if (!TID.isAsCheapAsAMove()) - return false; - if (!tii_->isTriviallyReMaterializable(DefMI, AA)) - return false; - bool SawStore = false; - if (!DefMI->isSafeToMove(tii_, AA, SawStore)) - return false; - if (TID.getNumDefs() != 1) - return false; - if (!DefMI->isImplicitDef()) { - // Make sure the copy destination register class fits the instruction - // definition register class. The mismatch can happen as a result of earlier - // extract_subreg, insert_subreg, subreg_to_reg coalescing. - const TargetRegisterClass *RC = TID.OpInfo[0].getRegClass(tri_); - if (TargetRegisterInfo::isVirtualRegister(DstReg)) { - if (mri_->getRegClass(DstReg) != RC) - return false; - } else if (!RC->contains(DstReg)) - return false; - } - - // If destination register has a sub-register index on it, make sure it - // matches the instruction register class. - if (DstSubIdx) { - const TargetInstrDesc &TID = DefMI->getDesc(); - if (TID.getNumDefs() != 1) - return false; - const TargetRegisterClass *DstRC = mri_->getRegClass(DstReg); - const TargetRegisterClass *DstSubRC = - DstRC->getSubRegisterRegClass(DstSubIdx); - const TargetRegisterClass *DefRC = TID.OpInfo[0].getRegClass(tri_); - if (DefRC == DstRC) - DstSubIdx = 0; - else if (DefRC != DstSubRC) - return false; - } - - RemoveCopyFlag(DstReg, CopyMI); - - MachineBasicBlock *MBB = CopyMI->getParent(); - MachineBasicBlock::iterator MII = - llvm::next(MachineBasicBlock::iterator(CopyMI)); - tii_->reMaterialize(*MBB, MII, DstReg, DstSubIdx, DefMI, *tri_); - MachineInstr *NewMI = prior(MII); - - // CopyMI may have implicit operands, transfer them over to the newly - // rematerialized instruction. And update implicit def interval valnos. - for (unsigned i = CopyMI->getDesc().getNumOperands(), - e = CopyMI->getNumOperands(); i != e; ++i) { - MachineOperand &MO = CopyMI->getOperand(i); - if (MO.isReg() && MO.isImplicit()) - NewMI->addOperand(MO); - if (MO.isDef()) - RemoveCopyFlag(MO.getReg(), CopyMI); - } - - NewMI->copyImplicitOps(CopyMI); - li_->ReplaceMachineInstrInMaps(CopyMI, NewMI); - CopyMI->eraseFromParent(); - ReMatCopies.insert(CopyMI); - ReMatDefs.insert(DefMI); - DEBUG(dbgs() << "Remat: " << *NewMI); - ++NumReMats; - - // The source interval can become smaller because we removed a use. - if (preserveSrcInt) - li_->shrinkToUses(&SrcInt); - - return true; -} - -/// UpdateRegDefsUses - Replace all defs and uses of SrcReg to DstReg and -/// update the subregister number if it is not zero. If DstReg is a -/// physical register and the existing subregister number of the def / use -/// being updated is not zero, make sure to set it to the correct physical -/// subregister. -void -SimpleRegisterCoalescing::UpdateRegDefsUses(const CoalescerPair &CP) { - bool DstIsPhys = CP.isPhys(); - unsigned SrcReg = CP.getSrcReg(); - unsigned DstReg = CP.getDstReg(); - unsigned SubIdx = CP.getSubIdx(); - - // Update LiveDebugVariables. - ldv_->renameRegister(SrcReg, DstReg, SubIdx); - - for (MachineRegisterInfo::reg_iterator I = mri_->reg_begin(SrcReg); - MachineInstr *UseMI = I.skipInstruction();) { - // A PhysReg copy that won't be coalesced can perhaps be rematerialized - // instead. - if (DstIsPhys) { - if (UseMI->isCopy() && - !UseMI->getOperand(1).getSubReg() && - !UseMI->getOperand(0).getSubReg() && - UseMI->getOperand(1).getReg() == SrcReg && - UseMI->getOperand(0).getReg() != SrcReg && - UseMI->getOperand(0).getReg() != DstReg && - !JoinedCopies.count(UseMI) && - ReMaterializeTrivialDef(li_->getInterval(SrcReg), false, - UseMI->getOperand(0).getReg(), 0, UseMI)) - continue; - } - - SmallVector Ops; - bool Reads, Writes; - tie(Reads, Writes) = UseMI->readsWritesVirtualRegister(SrcReg, &Ops); - bool Kills = false, Deads = false; - - // Replace SrcReg with DstReg in all UseMI operands. - for (unsigned i = 0, e = Ops.size(); i != e; ++i) { - MachineOperand &MO = UseMI->getOperand(Ops[i]); - Kills |= MO.isKill(); - Deads |= MO.isDead(); - - if (DstIsPhys) - MO.substPhysReg(DstReg, *tri_); - else - MO.substVirtReg(DstReg, SubIdx, *tri_); - } - - // This instruction is a copy that will be removed. - if (JoinedCopies.count(UseMI)) - continue; - - if (SubIdx) { - // If UseMI was a simple SrcReg def, make sure we didn't turn it into a - // read-modify-write of DstReg. - if (Deads) - UseMI->addRegisterDead(DstReg, tri_); - else if (!Reads && Writes) - UseMI->addRegisterDefined(DstReg, tri_); - - // Kill flags apply to the whole physical register. - if (DstIsPhys && Kills) - UseMI->addRegisterKilled(DstReg, tri_); - } - - DEBUG({ - dbgs() << "\t\tupdated: "; - if (!UseMI->isDebugValue()) - dbgs() << li_->getInstructionIndex(UseMI) << "\t"; - dbgs() << *UseMI; - }); - } -} - -/// removeIntervalIfEmpty - Check if the live interval of a physical register -/// is empty, if so remove it and also remove the empty intervals of its -/// sub-registers. Return true if live interval is removed. -static bool removeIntervalIfEmpty(LiveInterval &li, LiveIntervals *li_, - const TargetRegisterInfo *tri_) { - if (li.empty()) { - if (TargetRegisterInfo::isPhysicalRegister(li.reg)) - for (const unsigned* SR = tri_->getSubRegisters(li.reg); *SR; ++SR) { - if (!li_->hasInterval(*SR)) - continue; - LiveInterval &sli = li_->getInterval(*SR); - if (sli.empty()) - li_->removeInterval(*SR); - } - li_->removeInterval(li.reg); - return true; - } - return false; -} - -/// RemoveDeadDef - If a def of a live interval is now determined dead, remove -/// the val# it defines. If the live interval becomes empty, remove it as well. -bool SimpleRegisterCoalescing::RemoveDeadDef(LiveInterval &li, - MachineInstr *DefMI) { - SlotIndex DefIdx = li_->getInstructionIndex(DefMI).getDefIndex(); - LiveInterval::iterator MLR = li.FindLiveRangeContaining(DefIdx); - if (DefIdx != MLR->valno->def) - return false; - li.removeValNo(MLR->valno); - return removeIntervalIfEmpty(li, li_, tri_); -} - -void SimpleRegisterCoalescing::RemoveCopyFlag(unsigned DstReg, - const MachineInstr *CopyMI) { - SlotIndex DefIdx = li_->getInstructionIndex(CopyMI).getDefIndex(); - if (li_->hasInterval(DstReg)) { - LiveInterval &LI = li_->getInterval(DstReg); - if (const LiveRange *LR = LI.getLiveRangeContaining(DefIdx)) - if (LR->valno->def == DefIdx) - LR->valno->setCopy(0); - } - if (!TargetRegisterInfo::isPhysicalRegister(DstReg)) - return; - for (const unsigned* AS = tri_->getAliasSet(DstReg); *AS; ++AS) { - if (!li_->hasInterval(*AS)) - continue; - LiveInterval &LI = li_->getInterval(*AS); - if (const LiveRange *LR = LI.getLiveRangeContaining(DefIdx)) - if (LR->valno->def == DefIdx) - LR->valno->setCopy(0); - } -} - -/// shouldJoinPhys - Return true if a copy involving a physreg should be joined. -/// We need to be careful about coalescing a source physical register with a -/// virtual register. Once the coalescing is done, it cannot be broken and these -/// are not spillable! If the destination interval uses are far away, think -/// twice about coalescing them! -bool SimpleRegisterCoalescing::shouldJoinPhys(CoalescerPair &CP) { - bool Allocatable = li_->isAllocatable(CP.getDstReg()); - LiveInterval &JoinVInt = li_->getInterval(CP.getSrcReg()); - - /// Always join simple intervals that are defined by a single copy from a - /// reserved register. This doesn't increase register pressure, so it is - /// always beneficial. - if (!Allocatable && CP.isFlipped() && JoinVInt.containsOneValue()) - return true; - - if (!EnablePhysicalJoin) { - DEBUG(dbgs() << "\tPhysreg joins disabled.\n"); - return false; - } - - // Only coalesce to allocatable physreg, we don't want to risk modifying - // reserved registers. - if (!Allocatable) { - DEBUG(dbgs() << "\tRegister is an unallocatable physreg.\n"); - return false; // Not coalescable. - } - - // Don't join with physregs that have a ridiculous number of live - // ranges. The data structure performance is really bad when that - // happens. - if (li_->hasInterval(CP.getDstReg()) && - li_->getInterval(CP.getDstReg()).ranges.size() > 1000) { - ++numAborts; - DEBUG(dbgs() - << "\tPhysical register live interval too complicated, abort!\n"); - return false; - } - - // FIXME: Why are we skipping this test for partial copies? - // CodeGen/X86/phys_subreg_coalesce-3.ll needs it. - if (!CP.isPartial()) { - const TargetRegisterClass *RC = mri_->getRegClass(CP.getSrcReg()); - unsigned Threshold = RegClassInfo.getNumAllocatableRegs(RC) * 2; - unsigned Length = li_->getApproximateInstructionCount(JoinVInt); - if (Length > Threshold) { - ++numAborts; - DEBUG(dbgs() << "\tMay tie down a physical register, abort!\n"); - return false; - } - } - return true; -} - -/// isWinToJoinCrossClass - Return true if it's profitable to coalesce -/// two virtual registers from different register classes. -bool -SimpleRegisterCoalescing::isWinToJoinCrossClass(unsigned SrcReg, - unsigned DstReg, - const TargetRegisterClass *SrcRC, - const TargetRegisterClass *DstRC, - const TargetRegisterClass *NewRC) { - unsigned NewRCCount = RegClassInfo.getNumAllocatableRegs(NewRC); - // This heuristics is good enough in practice, but it's obviously not *right*. - // 4 is a magic number that works well enough for x86, ARM, etc. It filter - // out all but the most restrictive register classes. - if (NewRCCount > 4 || - // Early exit if the function is fairly small, coalesce aggressively if - // that's the case. For really special register classes with 3 or - // fewer registers, be a bit more careful. - (li_->getFuncInstructionCount() / NewRCCount) < 8) - return true; - LiveInterval &SrcInt = li_->getInterval(SrcReg); - LiveInterval &DstInt = li_->getInterval(DstReg); - unsigned SrcSize = li_->getApproximateInstructionCount(SrcInt); - unsigned DstSize = li_->getApproximateInstructionCount(DstInt); - - // Coalesce aggressively if the intervals are small compared to the number of - // registers in the new class. The number 4 is fairly arbitrary, chosen to be - // less aggressive than the 8 used for the whole function size. - const unsigned ThresSize = 4 * NewRCCount; - if (SrcSize <= ThresSize && DstSize <= ThresSize) - return true; - - // Estimate *register use density*. If it doubles or more, abort. - unsigned SrcUses = std::distance(mri_->use_nodbg_begin(SrcReg), - mri_->use_nodbg_end()); - unsigned DstUses = std::distance(mri_->use_nodbg_begin(DstReg), - mri_->use_nodbg_end()); - unsigned NewUses = SrcUses + DstUses; - unsigned NewSize = SrcSize + DstSize; - if (SrcRC != NewRC && SrcSize > ThresSize) { - unsigned SrcRCCount = RegClassInfo.getNumAllocatableRegs(SrcRC); - if (NewUses*SrcSize*SrcRCCount > 2*SrcUses*NewSize*NewRCCount) - return false; - } - if (DstRC != NewRC && DstSize > ThresSize) { - unsigned DstRCCount = RegClassInfo.getNumAllocatableRegs(DstRC); - if (NewUses*DstSize*DstRCCount > 2*DstUses*NewSize*NewRCCount) - return false; - } - return true; -} - - -/// JoinCopy - Attempt to join intervals corresponding to SrcReg/DstReg, -/// which are the src/dst of the copy instruction CopyMI. This returns true -/// if the copy was successfully coalesced away. If it is not currently -/// possible to coalesce this interval, but it may be possible if other -/// things get coalesced, then it returns true by reference in 'Again'. -bool SimpleRegisterCoalescing::JoinCopy(MachineInstr *CopyMI, bool &Again) { - - Again = false; - if (JoinedCopies.count(CopyMI) || ReMatCopies.count(CopyMI)) - return false; // Already done. - - DEBUG(dbgs() << li_->getInstructionIndex(CopyMI) << '\t' << *CopyMI); - - CoalescerPair CP(*tii_, *tri_); - if (!CP.setRegisters(CopyMI)) { - DEBUG(dbgs() << "\tNot coalescable.\n"); - return false; - } - - // If they are already joined we continue. - if (CP.getSrcReg() == CP.getDstReg()) { - markAsJoined(CopyMI); - DEBUG(dbgs() << "\tCopy already coalesced.\n"); - return false; // Not coalescable. - } - - DEBUG(dbgs() << "\tConsidering merging " << PrintReg(CP.getSrcReg(), tri_) - << " with " << PrintReg(CP.getDstReg(), tri_, CP.getSubIdx()) - << "\n"); - - // Enforce policies. - if (CP.isPhys()) { - if (!shouldJoinPhys(CP)) { - // Before giving up coalescing, if definition of source is defined by - // trivial computation, try rematerializing it. - if (!CP.isFlipped() && - ReMaterializeTrivialDef(li_->getInterval(CP.getSrcReg()), true, - CP.getDstReg(), 0, CopyMI)) - return true; - return false; - } - } else { - // Avoid constraining virtual register regclass too much. - if (CP.isCrossClass()) { - DEBUG(dbgs() << "\tCross-class to " << CP.getNewRC()->getName() << ".\n"); - if (DisableCrossClassJoin) { - DEBUG(dbgs() << "\tCross-class joins disabled.\n"); - return false; - } - if (!isWinToJoinCrossClass(CP.getSrcReg(), CP.getDstReg(), - mri_->getRegClass(CP.getSrcReg()), - mri_->getRegClass(CP.getDstReg()), - CP.getNewRC())) { - DEBUG(dbgs() << "\tAvoid coalescing to constrained register class.\n"); - Again = true; // May be possible to coalesce later. - return false; - } - } - - // When possible, let DstReg be the larger interval. - if (!CP.getSubIdx() && li_->getInterval(CP.getSrcReg()).ranges.size() > - li_->getInterval(CP.getDstReg()).ranges.size()) - CP.flip(); - } - - // Okay, attempt to join these two intervals. On failure, this returns false. - // Otherwise, if one of the intervals being joined is a physreg, this method - // always canonicalizes DstInt to be it. The output "SrcInt" will not have - // been modified, so we can use this information below to update aliases. - if (!JoinIntervals(CP)) { - // Coalescing failed. - - // If definition of source is defined by trivial computation, try - // rematerializing it. - if (!CP.isFlipped() && - ReMaterializeTrivialDef(li_->getInterval(CP.getSrcReg()), true, - CP.getDstReg(), 0, CopyMI)) - return true; - - // If we can eliminate the copy without merging the live ranges, do so now. - if (!CP.isPartial()) { - if (AdjustCopiesBackFrom(CP, CopyMI) || - RemoveCopyByCommutingDef(CP, CopyMI)) { - markAsJoined(CopyMI); - DEBUG(dbgs() << "\tTrivial!\n"); - return true; - } - } - - // Otherwise, we are unable to join the intervals. - DEBUG(dbgs() << "\tInterference!\n"); - Again = true; // May be possible to coalesce later. - return false; - } - - // Coalescing to a virtual register that is of a sub-register class of the - // other. Make sure the resulting register is set to the right register class. - if (CP.isCrossClass()) { - ++numCrossRCs; - mri_->setRegClass(CP.getDstReg(), CP.getNewRC()); - } - - // Remember to delete the copy instruction. - markAsJoined(CopyMI); - - UpdateRegDefsUses(CP); - - // If we have extended the live range of a physical register, make sure we - // update live-in lists as well. - if (CP.isPhys()) { - SmallVector BlockSeq; - // JoinIntervals invalidates the VNInfos in SrcInt, but we only need the - // ranges for this, and they are preserved. - LiveInterval &SrcInt = li_->getInterval(CP.getSrcReg()); - for (LiveInterval::const_iterator I = SrcInt.begin(), E = SrcInt.end(); - I != E; ++I ) { - li_->findLiveInMBBs(I->start, I->end, BlockSeq); - for (unsigned idx = 0, size = BlockSeq.size(); idx != size; ++idx) { - MachineBasicBlock &block = *BlockSeq[idx]; - if (!block.isLiveIn(CP.getDstReg())) - block.addLiveIn(CP.getDstReg()); - } - BlockSeq.clear(); - } - } - - // SrcReg is guarateed to be the register whose live interval that is - // being merged. - li_->removeInterval(CP.getSrcReg()); - - // Update regalloc hint. - tri_->UpdateRegAllocHint(CP.getSrcReg(), CP.getDstReg(), *mf_); - - DEBUG({ - LiveInterval &DstInt = li_->getInterval(CP.getDstReg()); - dbgs() << "\tJoined. Result = "; - DstInt.print(dbgs(), tri_); - dbgs() << "\n"; - }); - - ++numJoins; - return true; -} - -/// ComputeUltimateVN - Assuming we are going to join two live intervals, -/// compute what the resultant value numbers for each value in the input two -/// ranges will be. This is complicated by copies between the two which can -/// and will commonly cause multiple value numbers to be merged into one. -/// -/// VN is the value number that we're trying to resolve. InstDefiningValue -/// keeps track of the new InstDefiningValue assignment for the result -/// LiveInterval. ThisFromOther/OtherFromThis are sets that keep track of -/// whether a value in this or other is a copy from the opposite set. -/// ThisValNoAssignments/OtherValNoAssignments keep track of value #'s that have -/// already been assigned. -/// -/// ThisFromOther[x] - If x is defined as a copy from the other interval, this -/// contains the value number the copy is from. -/// -static unsigned ComputeUltimateVN(VNInfo *VNI, - SmallVector &NewVNInfo, - DenseMap &ThisFromOther, - DenseMap &OtherFromThis, - SmallVector &ThisValNoAssignments, - SmallVector &OtherValNoAssignments) { - unsigned VN = VNI->id; - - // If the VN has already been computed, just return it. - if (ThisValNoAssignments[VN] >= 0) - return ThisValNoAssignments[VN]; - assert(ThisValNoAssignments[VN] != -2 && "Cyclic value numbers"); - - // If this val is not a copy from the other val, then it must be a new value - // number in the destination. - DenseMap::iterator I = ThisFromOther.find(VNI); - if (I == ThisFromOther.end()) { - NewVNInfo.push_back(VNI); - return ThisValNoAssignments[VN] = NewVNInfo.size()-1; - } - VNInfo *OtherValNo = I->second; - - // Otherwise, this *is* a copy from the RHS. If the other side has already - // been computed, return it. - if (OtherValNoAssignments[OtherValNo->id] >= 0) - return ThisValNoAssignments[VN] = OtherValNoAssignments[OtherValNo->id]; - - // Mark this value number as currently being computed, then ask what the - // ultimate value # of the other value is. - ThisValNoAssignments[VN] = -2; - unsigned UltimateVN = - ComputeUltimateVN(OtherValNo, NewVNInfo, OtherFromThis, ThisFromOther, - OtherValNoAssignments, ThisValNoAssignments); - return ThisValNoAssignments[VN] = UltimateVN; -} - -/// JoinIntervals - Attempt to join these two intervals. On failure, this -/// returns false. -bool SimpleRegisterCoalescing::JoinIntervals(CoalescerPair &CP) { - LiveInterval &RHS = li_->getInterval(CP.getSrcReg()); - DEBUG({ dbgs() << "\t\tRHS = "; RHS.print(dbgs(), tri_); dbgs() << "\n"; }); - - // If a live interval is a physical register, check for interference with any - // aliases. The interference check implemented here is a bit more conservative - // than the full interfeence check below. We allow overlapping live ranges - // only when one is a copy of the other. - if (CP.isPhys()) { - for (const unsigned *AS = tri_->getAliasSet(CP.getDstReg()); *AS; ++AS){ - if (!li_->hasInterval(*AS)) - continue; - const LiveInterval &LHS = li_->getInterval(*AS); - LiveInterval::const_iterator LI = LHS.begin(); - for (LiveInterval::const_iterator RI = RHS.begin(), RE = RHS.end(); - RI != RE; ++RI) { - LI = std::lower_bound(LI, LHS.end(), RI->start); - // Does LHS have an overlapping live range starting before RI? - if ((LI != LHS.begin() && LI[-1].end > RI->start) && - (RI->start != RI->valno->def || - !CP.isCoalescable(li_->getInstructionFromIndex(RI->start)))) { - DEBUG({ - dbgs() << "\t\tInterference from alias: "; - LHS.print(dbgs(), tri_); - dbgs() << "\n\t\tOverlap at " << RI->start << " and no copy.\n"; - }); - return false; - } - - // Check that LHS ranges beginning in this range are copies. - for (; LI != LHS.end() && LI->start < RI->end; ++LI) { - if (LI->start != LI->valno->def || - !CP.isCoalescable(li_->getInstructionFromIndex(LI->start))) { - DEBUG({ - dbgs() << "\t\tInterference from alias: "; - LHS.print(dbgs(), tri_); - dbgs() << "\n\t\tDef at " << LI->start << " is not a copy.\n"; - }); - return false; - } - } - } - } - } - - // Compute the final value assignment, assuming that the live ranges can be - // coalesced. - SmallVector LHSValNoAssignments; - SmallVector RHSValNoAssignments; - DenseMap LHSValsDefinedFromRHS; - DenseMap RHSValsDefinedFromLHS; - SmallVector NewVNInfo; - - LiveInterval &LHS = li_->getOrCreateInterval(CP.getDstReg()); - DEBUG({ dbgs() << "\t\tLHS = "; LHS.print(dbgs(), tri_); dbgs() << "\n"; }); - - // Loop over the value numbers of the LHS, seeing if any are defined from - // the RHS. - for (LiveInterval::vni_iterator i = LHS.vni_begin(), e = LHS.vni_end(); - i != e; ++i) { - VNInfo *VNI = *i; - if (VNI->isUnused() || !VNI->isDefByCopy()) // Src not defined by a copy? - continue; - - // Never join with a register that has EarlyClobber redefs. - if (VNI->hasRedefByEC()) - return false; - - // DstReg is known to be a register in the LHS interval. If the src is - // from the RHS interval, we can use its value #. - if (!CP.isCoalescable(VNI->getCopy())) - continue; - - // Figure out the value # from the RHS. - LiveRange *lr = RHS.getLiveRangeContaining(VNI->def.getPrevSlot()); - // The copy could be to an aliased physreg. - if (!lr) continue; - LHSValsDefinedFromRHS[VNI] = lr->valno; - } - - // Loop over the value numbers of the RHS, seeing if any are defined from - // the LHS. - for (LiveInterval::vni_iterator i = RHS.vni_begin(), e = RHS.vni_end(); - i != e; ++i) { - VNInfo *VNI = *i; - if (VNI->isUnused() || !VNI->isDefByCopy()) // Src not defined by a copy? - continue; - - // Never join with a register that has EarlyClobber redefs. - if (VNI->hasRedefByEC()) - return false; - - // DstReg is known to be a register in the RHS interval. If the src is - // from the LHS interval, we can use its value #. - if (!CP.isCoalescable(VNI->getCopy())) - continue; - - // Figure out the value # from the LHS. - LiveRange *lr = LHS.getLiveRangeContaining(VNI->def.getPrevSlot()); - // The copy could be to an aliased physreg. - if (!lr) continue; - RHSValsDefinedFromLHS[VNI] = lr->valno; - } - - LHSValNoAssignments.resize(LHS.getNumValNums(), -1); - RHSValNoAssignments.resize(RHS.getNumValNums(), -1); - NewVNInfo.reserve(LHS.getNumValNums() + RHS.getNumValNums()); - - for (LiveInterval::vni_iterator i = LHS.vni_begin(), e = LHS.vni_end(); - i != e; ++i) { - VNInfo *VNI = *i; - unsigned VN = VNI->id; - if (LHSValNoAssignments[VN] >= 0 || VNI->isUnused()) - continue; - ComputeUltimateVN(VNI, NewVNInfo, - LHSValsDefinedFromRHS, RHSValsDefinedFromLHS, - LHSValNoAssignments, RHSValNoAssignments); - } - for (LiveInterval::vni_iterator i = RHS.vni_begin(), e = RHS.vni_end(); - i != e; ++i) { - VNInfo *VNI = *i; - unsigned VN = VNI->id; - if (RHSValNoAssignments[VN] >= 0 || VNI->isUnused()) - continue; - // If this value number isn't a copy from the LHS, it's a new number. - if (RHSValsDefinedFromLHS.find(VNI) == RHSValsDefinedFromLHS.end()) { - NewVNInfo.push_back(VNI); - RHSValNoAssignments[VN] = NewVNInfo.size()-1; - continue; - } - - ComputeUltimateVN(VNI, NewVNInfo, - RHSValsDefinedFromLHS, LHSValsDefinedFromRHS, - RHSValNoAssignments, LHSValNoAssignments); - } - - // Armed with the mappings of LHS/RHS values to ultimate values, walk the - // interval lists to see if these intervals are coalescable. - LiveInterval::const_iterator I = LHS.begin(); - LiveInterval::const_iterator IE = LHS.end(); - LiveInterval::const_iterator J = RHS.begin(); - LiveInterval::const_iterator JE = RHS.end(); - - // Skip ahead until the first place of potential sharing. - if (I != IE && J != JE) { - if (I->start < J->start) { - I = std::upper_bound(I, IE, J->start); - if (I != LHS.begin()) --I; - } else if (J->start < I->start) { - J = std::upper_bound(J, JE, I->start); - if (J != RHS.begin()) --J; - } - } - - while (I != IE && J != JE) { - // Determine if these two live ranges overlap. - bool Overlaps; - if (I->start < J->start) { - Overlaps = I->end > J->start; - } else { - Overlaps = J->end > I->start; - } - - // If so, check value # info to determine if they are really different. - if (Overlaps) { - // If the live range overlap will map to the same value number in the - // result liverange, we can still coalesce them. If not, we can't. - if (LHSValNoAssignments[I->valno->id] != - RHSValNoAssignments[J->valno->id]) - return false; - // If it's re-defined by an early clobber somewhere in the live range, - // then conservatively abort coalescing. - if (NewVNInfo[LHSValNoAssignments[I->valno->id]]->hasRedefByEC()) - return false; - } - - if (I->end < J->end) - ++I; - else - ++J; - } - - // Update kill info. Some live ranges are extended due to copy coalescing. - for (DenseMap::iterator I = LHSValsDefinedFromRHS.begin(), - E = LHSValsDefinedFromRHS.end(); I != E; ++I) { - VNInfo *VNI = I->first; - unsigned LHSValID = LHSValNoAssignments[VNI->id]; - if (VNI->hasPHIKill()) - NewVNInfo[LHSValID]->setHasPHIKill(true); - } - - // Update kill info. Some live ranges are extended due to copy coalescing. - for (DenseMap::iterator I = RHSValsDefinedFromLHS.begin(), - E = RHSValsDefinedFromLHS.end(); I != E; ++I) { - VNInfo *VNI = I->first; - unsigned RHSValID = RHSValNoAssignments[VNI->id]; - if (VNI->hasPHIKill()) - NewVNInfo[RHSValID]->setHasPHIKill(true); - } - - if (LHSValNoAssignments.empty()) - LHSValNoAssignments.push_back(-1); - if (RHSValNoAssignments.empty()) - RHSValNoAssignments.push_back(-1); - - // If we get here, we know that we can coalesce the live ranges. Ask the - // intervals to coalesce themselves now. - LHS.join(RHS, &LHSValNoAssignments[0], &RHSValNoAssignments[0], NewVNInfo, - mri_); - return true; -} - -namespace { - // DepthMBBCompare - Comparison predicate that sort first based on the loop - // depth of the basic block (the unsigned), and then on the MBB number. - struct DepthMBBCompare { - typedef std::pair DepthMBBPair; - bool operator()(const DepthMBBPair &LHS, const DepthMBBPair &RHS) const { - // Deeper loops first - if (LHS.first != RHS.first) - return LHS.first > RHS.first; - - // Prefer blocks that are more connected in the CFG. This takes care of - // the most difficult copies first while intervals are short. - unsigned cl = LHS.second->pred_size() + LHS.second->succ_size(); - unsigned cr = RHS.second->pred_size() + RHS.second->succ_size(); - if (cl != cr) - return cl > cr; - - // As a last resort, sort by block number. - return LHS.second->getNumber() < RHS.second->getNumber(); - } - }; -} - -void SimpleRegisterCoalescing::CopyCoalesceInMBB(MachineBasicBlock *MBB, - std::vector &TryAgain) { - DEBUG(dbgs() << MBB->getName() << ":\n"); - - SmallVector VirtCopies; - SmallVector PhysCopies; - SmallVector ImpDefCopies; - for (MachineBasicBlock::iterator MII = MBB->begin(), E = MBB->end(); - MII != E;) { - MachineInstr *Inst = MII++; - - // If this isn't a copy nor a extract_subreg, we can't join intervals. - unsigned SrcReg, DstReg; - if (Inst->isCopy()) { - DstReg = Inst->getOperand(0).getReg(); - SrcReg = Inst->getOperand(1).getReg(); - } else if (Inst->isSubregToReg()) { - DstReg = Inst->getOperand(0).getReg(); - SrcReg = Inst->getOperand(2).getReg(); - } else - continue; - - bool SrcIsPhys = TargetRegisterInfo::isPhysicalRegister(SrcReg); - bool DstIsPhys = TargetRegisterInfo::isPhysicalRegister(DstReg); - if (li_->hasInterval(SrcReg) && li_->getInterval(SrcReg).empty()) - ImpDefCopies.push_back(Inst); - else if (SrcIsPhys || DstIsPhys) - PhysCopies.push_back(Inst); - else - VirtCopies.push_back(Inst); - } - - // Try coalescing implicit copies and insert_subreg first, - // followed by copies to / from physical registers, then finally copies - // from virtual registers to virtual registers. - for (unsigned i = 0, e = ImpDefCopies.size(); i != e; ++i) { - MachineInstr *TheCopy = ImpDefCopies[i]; - bool Again = false; - if (!JoinCopy(TheCopy, Again)) - if (Again) - TryAgain.push_back(TheCopy); - } - for (unsigned i = 0, e = PhysCopies.size(); i != e; ++i) { - MachineInstr *TheCopy = PhysCopies[i]; - bool Again = false; - if (!JoinCopy(TheCopy, Again)) - if (Again) - TryAgain.push_back(TheCopy); - } - for (unsigned i = 0, e = VirtCopies.size(); i != e; ++i) { - MachineInstr *TheCopy = VirtCopies[i]; - bool Again = false; - if (!JoinCopy(TheCopy, Again)) - if (Again) - TryAgain.push_back(TheCopy); - } -} - -void SimpleRegisterCoalescing::joinIntervals() { - DEBUG(dbgs() << "********** JOINING INTERVALS ***********\n"); - - std::vector TryAgainList; - if (loopInfo->empty()) { - // If there are no loops in the function, join intervals in function order. - for (MachineFunction::iterator I = mf_->begin(), E = mf_->end(); - I != E; ++I) - CopyCoalesceInMBB(I, TryAgainList); - } else { - // Otherwise, join intervals in inner loops before other intervals. - // Unfortunately we can't just iterate over loop hierarchy here because - // there may be more MBB's than BB's. Collect MBB's for sorting. - - // Join intervals in the function prolog first. We want to join physical - // registers with virtual registers before the intervals got too long. - std::vector > MBBs; - for (MachineFunction::iterator I = mf_->begin(), E = mf_->end();I != E;++I){ - MachineBasicBlock *MBB = I; - MBBs.push_back(std::make_pair(loopInfo->getLoopDepth(MBB), I)); - } - - // Sort by loop depth. - std::sort(MBBs.begin(), MBBs.end(), DepthMBBCompare()); - - // Finally, join intervals in loop nest order. - for (unsigned i = 0, e = MBBs.size(); i != e; ++i) - CopyCoalesceInMBB(MBBs[i].second, TryAgainList); - } - - // Joining intervals can allow other intervals to be joined. Iteratively join - // until we make no progress. - bool ProgressMade = true; - while (ProgressMade) { - ProgressMade = false; - - for (unsigned i = 0, e = TryAgainList.size(); i != e; ++i) { - MachineInstr *&TheCopy = TryAgainList[i]; - if (!TheCopy) - continue; - - bool Again = false; - bool Success = JoinCopy(TheCopy, Again); - if (Success || !Again) { - TheCopy= 0; // Mark this one as done. - ProgressMade = true; - } - } - } -} - -void SimpleRegisterCoalescing::releaseMemory() { - JoinedCopies.clear(); - ReMatCopies.clear(); - ReMatDefs.clear(); -} - -bool SimpleRegisterCoalescing::runOnMachineFunction(MachineFunction &fn) { - mf_ = &fn; - mri_ = &fn.getRegInfo(); - tm_ = &fn.getTarget(); - tri_ = tm_->getRegisterInfo(); - tii_ = tm_->getInstrInfo(); - li_ = &getAnalysis(); - ldv_ = &getAnalysis(); - AA = &getAnalysis(); - loopInfo = &getAnalysis(); - - DEBUG(dbgs() << "********** SIMPLE REGISTER COALESCING **********\n" - << "********** Function: " - << ((Value*)mf_->getFunction())->getName() << '\n'); - - if (VerifyCoalescing) - mf_->verify(this, "Before register coalescing"); - - RegClassInfo.runOnMachineFunction(fn); - - // Join (coalesce) intervals if requested. - if (EnableJoining) { - joinIntervals(); - DEBUG({ - dbgs() << "********** INTERVALS POST JOINING **********\n"; - for (LiveIntervals::iterator I = li_->begin(), E = li_->end(); - I != E; ++I){ - I->second->print(dbgs(), tri_); - dbgs() << "\n"; - } - }); - } - - // Perform a final pass over the instructions and compute spill weights - // and remove identity moves. - SmallVector DeadDefs; - for (MachineFunction::iterator mbbi = mf_->begin(), mbbe = mf_->end(); - mbbi != mbbe; ++mbbi) { - MachineBasicBlock* mbb = mbbi; - for (MachineBasicBlock::iterator mii = mbb->begin(), mie = mbb->end(); - mii != mie; ) { - MachineInstr *MI = mii; - if (JoinedCopies.count(MI)) { - // Delete all coalesced copies. - bool DoDelete = true; - assert(MI->isCopyLike() && "Unrecognized copy instruction"); - unsigned SrcReg = MI->getOperand(MI->isSubregToReg() ? 2 : 1).getReg(); - if (TargetRegisterInfo::isPhysicalRegister(SrcReg) && - MI->getNumOperands() > 2) - // Do not delete extract_subreg, insert_subreg of physical - // registers unless the definition is dead. e.g. - // %DO = INSERT_SUBREG %D0, %S0, 1 - // or else the scavenger may complain. LowerSubregs will - // delete them later. - DoDelete = false; - - if (MI->allDefsAreDead()) { - if (TargetRegisterInfo::isVirtualRegister(SrcReg) && - li_->hasInterval(SrcReg)) - li_->shrinkToUses(&li_->getInterval(SrcReg)); - DoDelete = true; - } - if (!DoDelete) { - // We need the instruction to adjust liveness, so make it a KILL. - if (MI->isSubregToReg()) { - MI->RemoveOperand(3); - MI->RemoveOperand(1); - } - MI->setDesc(tii_->get(TargetOpcode::KILL)); - mii = llvm::next(mii); - } else { - li_->RemoveMachineInstrFromMaps(MI); - mii = mbbi->erase(mii); - ++numPeep; - } - continue; - } - - // Now check if this is a remat'ed def instruction which is now dead. - if (ReMatDefs.count(MI)) { - bool isDead = true; - for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { - const MachineOperand &MO = MI->getOperand(i); - if (!MO.isReg()) - continue; - unsigned Reg = MO.getReg(); - if (!Reg) - continue; - if (TargetRegisterInfo::isVirtualRegister(Reg)) - DeadDefs.push_back(Reg); - if (MO.isDead()) - continue; - if (TargetRegisterInfo::isPhysicalRegister(Reg) || - !mri_->use_nodbg_empty(Reg)) { - isDead = false; - break; - } - } - if (isDead) { - while (!DeadDefs.empty()) { - unsigned DeadDef = DeadDefs.back(); - DeadDefs.pop_back(); - RemoveDeadDef(li_->getInterval(DeadDef), MI); - } - li_->RemoveMachineInstrFromMaps(mii); - mii = mbbi->erase(mii); - continue; - } else - DeadDefs.clear(); - } - - ++mii; - - // Check for now unnecessary kill flags. - if (li_->isNotInMIMap(MI)) continue; - SlotIndex DefIdx = li_->getInstructionIndex(MI).getDefIndex(); - for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { - MachineOperand &MO = MI->getOperand(i); - if (!MO.isReg() || !MO.isKill()) continue; - unsigned reg = MO.getReg(); - if (!reg || !li_->hasInterval(reg)) continue; - if (!li_->getInterval(reg).killedAt(DefIdx)) { - MO.setIsKill(false); - continue; - } - // When leaving a kill flag on a physreg, check if any subregs should - // remain alive. - if (!TargetRegisterInfo::isPhysicalRegister(reg)) - continue; - for (const unsigned *SR = tri_->getSubRegisters(reg); - unsigned S = *SR; ++SR) - if (li_->hasInterval(S) && li_->getInterval(S).liveAt(DefIdx)) - MI->addRegisterDefined(S, tri_); - } - } - } - - DEBUG(dump()); - DEBUG(ldv_->dump()); - if (VerifyCoalescing) - mf_->verify(this, "After register coalescing"); - return true; -} - -/// print - Implement the dump method. -void SimpleRegisterCoalescing::print(raw_ostream &O, const Module* m) const { - li_->print(O, m); -} - -RegisterCoalescer* llvm::createSimpleRegisterCoalescer() { - return new SimpleRegisterCoalescing(); -} - -// Make sure that anything that uses RegisterCoalescer pulls in this file... -DEFINING_FILE_FOR(SimpleRegisterCoalescing) -- cgit v1.1 From 5b220213bfe9c37c2bb41a7ae0804e06a14f1007 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Sun, 26 Jun 2011 22:34:10 +0000 Subject: There is only one register coalescer. Merge it into the base class and remove the analysis group. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133899 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CodeGen/LinkAllCodegenComponents.h | 2 - include/llvm/CodeGen/Passes.h | 9 +- include/llvm/InitializePasses.h | 3 +- lib/CodeGen/CodeGen.cpp | 3 +- lib/CodeGen/RegAllocBasic.cpp | 2 +- lib/CodeGen/RegAllocGreedy.cpp | 2 +- lib/CodeGen/RegAllocLinearScan.cpp | 4 +- lib/CodeGen/RegAllocPBQP.cpp | 2 +- lib/CodeGen/RegisterCoalescer.cpp | 76 +++---- lib/CodeGen/RegisterCoalescer.h | 255 +++++++++++------------- lib/CodeGen/SplitKit.cpp | 4 +- 11 files changed, 154 insertions(+), 208 deletions(-) diff --git a/include/llvm/CodeGen/LinkAllCodegenComponents.h b/include/llvm/CodeGen/LinkAllCodegenComponents.h index c931261..098dd0b 100644 --- a/include/llvm/CodeGen/LinkAllCodegenComponents.h +++ b/include/llvm/CodeGen/LinkAllCodegenComponents.h @@ -39,8 +39,6 @@ namespace { (void) llvm::createGreedyRegisterAllocator(); (void) llvm::createDefaultPBQPRegisterAllocator(); - (void) llvm::createSimpleRegisterCoalescer(); - llvm::linkOcamlGC(); llvm::linkShadowStackGC(); diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h index 53aee7a..b0e9213 100644 --- a/include/llvm/CodeGen/Passes.h +++ b/include/llvm/CodeGen/Passes.h @@ -78,11 +78,6 @@ namespace llvm { /// LiveStacks pass. An analysis keeping track of the liveness of stack slots. extern char &LiveStacksID; - /// SimpleRegisterCoalescing pass. Aggressively coalesces every register - /// copy it can. - /// - extern char &SimpleRegisterCoalescingID; - /// TwoAddressInstruction pass - This pass reduces two-address instructions to /// use two operands. This destroys SSA information but it is desired by /// register allocators. @@ -132,10 +127,10 @@ namespace llvm { /// FunctionPass *createDefaultPBQPRegisterAllocator(); - /// SimpleRegisterCoalescing Pass - Coalesce all copies possible. Can run + /// RegisterCoalescer Pass - Coalesce all copies possible. Can run /// independently of the register allocator. /// - RegisterCoalescer *createSimpleRegisterCoalescer(); + RegisterCoalescer *createRegisterCoalescer(); /// PrologEpilogCodeInserter Pass - This pass inserts prolog and epilog code, /// and eliminates abstract frame references. diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h index 5dfc4b3..89d0ac8 100644 --- a/include/llvm/InitializePasses.h +++ b/include/llvm/InitializePasses.h @@ -198,7 +198,6 @@ void initializeRegionOnlyPrinterPass(PassRegistry&); void initializeRegionOnlyViewerPass(PassRegistry&); void initializeRegionPrinterPass(PassRegistry&); void initializeRegionViewerPass(PassRegistry&); -void initializeRegisterCoalescerAnalysisGroup(PassRegistry&); void initializeRenderMachineFunctionPass(PassRegistry&); void initializeSCCPPass(PassRegistry&); void initializeSROA_DTPass(PassRegistry&); @@ -206,7 +205,7 @@ void initializeSROA_SSAUpPass(PassRegistry&); void initializeScalarEvolutionAliasAnalysisPass(PassRegistry&); void initializeScalarEvolutionPass(PassRegistry&); void initializeSimpleInlinerPass(PassRegistry&); -void initializeSimpleRegisterCoalescingPass(PassRegistry&); +void initializeRegisterCoalescerPass(PassRegistry&); void initializeSimplifyLibCallsPass(PassRegistry&); void initializeSingleLoopExtractorPass(PassRegistry&); void initializeSinkingPass(PassRegistry&); diff --git a/lib/CodeGen/CodeGen.cpp b/lib/CodeGen/CodeGen.cpp index 515e6f9..35923c6 100644 --- a/lib/CodeGen/CodeGen.cpp +++ b/lib/CodeGen/CodeGen.cpp @@ -41,9 +41,8 @@ void llvm::initializeCodeGen(PassRegistry &Registry) { initializeProcessImplicitDefsPass(Registry); initializePEIPass(Registry); initializeRALinScanPass(Registry); - initializeRegisterCoalescerAnalysisGroup(Registry); + initializeRegisterCoalescerPass(Registry); initializeRenderMachineFunctionPass(Registry); - initializeSimpleRegisterCoalescingPass(Registry); initializeSlotIndexesPass(Registry); initializeLoopSplitterPass(Registry); initializeStackProtectorPass(Registry); diff --git a/lib/CodeGen/RegAllocBasic.cpp b/lib/CodeGen/RegAllocBasic.cpp index 7961be3..bcb38d7 100644 --- a/lib/CodeGen/RegAllocBasic.cpp +++ b/lib/CodeGen/RegAllocBasic.cpp @@ -141,7 +141,7 @@ RABasic::RABasic(): MachineFunctionPass(ID) { initializeLiveIntervalsPass(*PassRegistry::getPassRegistry()); initializeSlotIndexesPass(*PassRegistry::getPassRegistry()); initializeStrongPHIEliminationPass(*PassRegistry::getPassRegistry()); - initializeRegisterCoalescerAnalysisGroup(*PassRegistry::getPassRegistry()); + initializeRegisterCoalescerPass(*PassRegistry::getPassRegistry()); initializeCalculateSpillWeightsPass(*PassRegistry::getPassRegistry()); initializeLiveStacksPass(*PassRegistry::getPassRegistry()); initializeMachineDominatorTreePass(*PassRegistry::getPassRegistry()); diff --git a/lib/CodeGen/RegAllocGreedy.cpp b/lib/CodeGen/RegAllocGreedy.cpp index b2db2de..d0e6a64 100644 --- a/lib/CodeGen/RegAllocGreedy.cpp +++ b/lib/CodeGen/RegAllocGreedy.cpp @@ -234,7 +234,7 @@ RAGreedy::RAGreedy(): MachineFunctionPass(ID), LRStage(RS_New) { initializeLiveIntervalsPass(*PassRegistry::getPassRegistry()); initializeSlotIndexesPass(*PassRegistry::getPassRegistry()); initializeStrongPHIEliminationPass(*PassRegistry::getPassRegistry()); - initializeRegisterCoalescerAnalysisGroup(*PassRegistry::getPassRegistry()); + initializeRegisterCoalescerPass(*PassRegistry::getPassRegistry()); initializeCalculateSpillWeightsPass(*PassRegistry::getPassRegistry()); initializeLiveStacksPass(*PassRegistry::getPassRegistry()); initializeMachineDominatorTreePass(*PassRegistry::getPassRegistry()); diff --git a/lib/CodeGen/RegAllocLinearScan.cpp b/lib/CodeGen/RegAllocLinearScan.cpp index dd5a605..2ad0747 100644 --- a/lib/CodeGen/RegAllocLinearScan.cpp +++ b/lib/CodeGen/RegAllocLinearScan.cpp @@ -101,7 +101,7 @@ namespace { initializeLiveDebugVariablesPass(*PassRegistry::getPassRegistry()); initializeLiveIntervalsPass(*PassRegistry::getPassRegistry()); initializeStrongPHIEliminationPass(*PassRegistry::getPassRegistry()); - initializeRegisterCoalescerAnalysisGroup( + initializeRegisterCoalescerPass( *PassRegistry::getPassRegistry()); initializeCalculateSpillWeightsPass(*PassRegistry::getPassRegistry()); initializePreAllocSplittingPass(*PassRegistry::getPassRegistry()); @@ -405,7 +405,7 @@ INITIALIZE_PASS_DEPENDENCY(PreAllocSplitting) INITIALIZE_PASS_DEPENDENCY(LiveStacks) INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo) INITIALIZE_PASS_DEPENDENCY(VirtRegMap) -INITIALIZE_AG_DEPENDENCY(RegisterCoalescer) +INITIALIZE_PASS_DEPENDENCY(RegisterCoalescer) INITIALIZE_AG_DEPENDENCY(AliasAnalysis) INITIALIZE_PASS_END(RALinScan, "linearscan-regalloc", "Linear Scan Register Allocator", false, false) diff --git a/lib/CodeGen/RegAllocPBQP.cpp b/lib/CodeGen/RegAllocPBQP.cpp index d675841..72230d4 100644 --- a/lib/CodeGen/RegAllocPBQP.cpp +++ b/lib/CodeGen/RegAllocPBQP.cpp @@ -88,7 +88,7 @@ public: : MachineFunctionPass(ID), builder(b), customPassID(cPassID) { initializeSlotIndexesPass(*PassRegistry::getPassRegistry()); initializeLiveIntervalsPass(*PassRegistry::getPassRegistry()); - initializeRegisterCoalescerAnalysisGroup(*PassRegistry::getPassRegistry()); + initializeRegisterCoalescerPass(*PassRegistry::getPassRegistry()); initializeCalculateSpillWeightsPass(*PassRegistry::getPassRegistry()); initializeLiveStacksPass(*PassRegistry::getPassRegistry()); initializeMachineLoopInfoPass(*PassRegistry::getPassRegistry()); diff --git a/lib/CodeGen/RegisterCoalescer.cpp b/lib/CodeGen/RegisterCoalescer.cpp index d0dcbb5..06a26a7 100644 --- a/lib/CodeGen/RegisterCoalescer.cpp +++ b/lib/CodeGen/RegisterCoalescer.cpp @@ -55,7 +55,6 @@ STATISTIC(NumReMats , "Number of instructions re-materialized"); STATISTIC(numPeep , "Number of identity moves eliminated after coalescing"); STATISTIC(numAborts , "Number of times interval joining aborted"); -char SimpleRegisterCoalescing::ID = 0; static cl::opt EnableJoining("join-liveintervals", cl::desc("Coalesce copies (default=true)"), @@ -76,9 +75,8 @@ VerifyCoalescing("verify-coalescing", cl::desc("Verify machine instrs before and after register coalescing"), cl::Hidden); -INITIALIZE_AG_PASS_BEGIN(SimpleRegisterCoalescing, RegisterCoalescer, - "simple-register-coalescing", "Simple Register Coalescing", - false, false, true) +INITIALIZE_PASS_BEGIN(RegisterCoalescer, "simple-register-coalescing", + "Simple Register Coalescing", false, false) INITIALIZE_PASS_DEPENDENCY(LiveIntervals) INITIALIZE_PASS_DEPENDENCY(LiveDebugVariables) INITIALIZE_PASS_DEPENDENCY(SlotIndexes) @@ -87,25 +85,11 @@ INITIALIZE_PASS_DEPENDENCY(StrongPHIElimination) INITIALIZE_PASS_DEPENDENCY(PHIElimination) INITIALIZE_PASS_DEPENDENCY(TwoAddressInstructionPass) INITIALIZE_AG_DEPENDENCY(AliasAnalysis) -INITIALIZE_AG_PASS_END(SimpleRegisterCoalescing, RegisterCoalescer, - "simple-register-coalescing", "Simple Register Coalescing", - false, false, true) +INITIALIZE_PASS_END(RegisterCoalescer, "simple-register-coalescing", + "Simple Register Coalescing", false, false) -char &llvm::SimpleRegisterCoalescingID = SimpleRegisterCoalescing::ID; - -// Register the RegisterCoalescer interface, providing a nice name to refer to. -INITIALIZE_ANALYSIS_GROUP(RegisterCoalescer, "Register Coalescer", - SimpleRegisterCoalescing) char RegisterCoalescer::ID = 0; -// RegisterCoalescer destructor: DO NOT move this to the header file -// for RegisterCoalescer or else clients of the RegisterCoalescer -// class may not depend on the RegisterCoalescer.o file in the current -// .a file, causing alias analysis support to not be included in the -// tool correctly! -// -RegisterCoalescer::~RegisterCoalescer() {} - unsigned CoalescerPair::compose(unsigned a, unsigned b) const { if (!a) return b; if (!b) return a; @@ -259,14 +243,7 @@ bool CoalescerPair::isCoalescable(const MachineInstr *MI) const { } } -// Because of the way .a files work, we must force the SimpleRC -// implementation to be pulled in if the RegisterCoalescer classes are -// pulled in. Otherwise we run the risk of RegisterCoalescer being -// used, but the default implementation not being linked into the tool -// that uses it. -DEFINING_FILE_FOR(RegisterCoalescer) - -void SimpleRegisterCoalescing::getAnalysisUsage(AnalysisUsage &AU) const { +void RegisterCoalescer::getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesCFG(); AU.addRequired(); AU.addRequired(); @@ -283,7 +260,7 @@ void SimpleRegisterCoalescing::getAnalysisUsage(AnalysisUsage &AU) const { MachineFunctionPass::getAnalysisUsage(AU); } -void SimpleRegisterCoalescing::markAsJoined(MachineInstr *CopyMI) { +void RegisterCoalescer::markAsJoined(MachineInstr *CopyMI) { /// Joined copies are not deleted immediately, but kept in JoinedCopies. JoinedCopies.insert(CopyMI); @@ -310,7 +287,7 @@ void SimpleRegisterCoalescing::markAsJoined(MachineInstr *CopyMI) { /// /// This returns true if an interval was modified. /// -bool SimpleRegisterCoalescing::AdjustCopiesBackFrom(const CoalescerPair &CP, +bool RegisterCoalescer::AdjustCopiesBackFrom(const CoalescerPair &CP, MachineInstr *CopyMI) { // Bail if there is no dst interval - can happen when merging physical subreg // operations. @@ -464,7 +441,7 @@ bool SimpleRegisterCoalescing::AdjustCopiesBackFrom(const CoalescerPair &CP, /// HasOtherReachingDefs - Return true if there are definitions of IntB /// other than BValNo val# that can reach uses of AValno val# of IntA. -bool SimpleRegisterCoalescing::HasOtherReachingDefs(LiveInterval &IntA, +bool RegisterCoalescer::HasOtherReachingDefs(LiveInterval &IntA, LiveInterval &IntB, VNInfo *AValNo, VNInfo *BValNo) { @@ -510,7 +487,7 @@ bool SimpleRegisterCoalescing::HasOtherReachingDefs(LiveInterval &IntA, /// /// This returns true if an interval was modified. /// -bool SimpleRegisterCoalescing::RemoveCopyByCommutingDef(const CoalescerPair &CP, +bool RegisterCoalescer::RemoveCopyByCommutingDef(const CoalescerPair &CP, MachineInstr *CopyMI) { // FIXME: For now, only eliminate the copy by commuting its def when the // source register is a virtual register. We want to guard against cases @@ -693,7 +670,7 @@ bool SimpleRegisterCoalescing::RemoveCopyByCommutingDef(const CoalescerPair &CP, /// ReMaterializeTrivialDef - If the source of a copy is defined by a trivial /// computation, replace the copy by rematerialize the definition. -bool SimpleRegisterCoalescing::ReMaterializeTrivialDef(LiveInterval &SrcInt, +bool RegisterCoalescer::ReMaterializeTrivialDef(LiveInterval &SrcInt, bool preserveSrcInt, unsigned DstReg, unsigned DstSubIdx, @@ -788,7 +765,7 @@ bool SimpleRegisterCoalescing::ReMaterializeTrivialDef(LiveInterval &SrcInt, /// being updated is not zero, make sure to set it to the correct physical /// subregister. void -SimpleRegisterCoalescing::UpdateRegDefsUses(const CoalescerPair &CP) { +RegisterCoalescer::UpdateRegDefsUses(const CoalescerPair &CP) { bool DstIsPhys = CP.isPhys(); unsigned SrcReg = CP.getSrcReg(); unsigned DstReg = CP.getDstReg(); @@ -879,7 +856,7 @@ static bool removeIntervalIfEmpty(LiveInterval &li, LiveIntervals *li_, /// RemoveDeadDef - If a def of a live interval is now determined dead, remove /// the val# it defines. If the live interval becomes empty, remove it as well. -bool SimpleRegisterCoalescing::RemoveDeadDef(LiveInterval &li, +bool RegisterCoalescer::RemoveDeadDef(LiveInterval &li, MachineInstr *DefMI) { SlotIndex DefIdx = li_->getInstructionIndex(DefMI).getDefIndex(); LiveInterval::iterator MLR = li.FindLiveRangeContaining(DefIdx); @@ -889,7 +866,7 @@ bool SimpleRegisterCoalescing::RemoveDeadDef(LiveInterval &li, return removeIntervalIfEmpty(li, li_, tri_); } -void SimpleRegisterCoalescing::RemoveCopyFlag(unsigned DstReg, +void RegisterCoalescer::RemoveCopyFlag(unsigned DstReg, const MachineInstr *CopyMI) { SlotIndex DefIdx = li_->getInstructionIndex(CopyMI).getDefIndex(); if (li_->hasInterval(DstReg)) { @@ -915,7 +892,7 @@ void SimpleRegisterCoalescing::RemoveCopyFlag(unsigned DstReg, /// virtual register. Once the coalescing is done, it cannot be broken and these /// are not spillable! If the destination interval uses are far away, think /// twice about coalescing them! -bool SimpleRegisterCoalescing::shouldJoinPhys(CoalescerPair &CP) { +bool RegisterCoalescer::shouldJoinPhys(CoalescerPair &CP) { bool Allocatable = li_->isAllocatable(CP.getDstReg()); LiveInterval &JoinVInt = li_->getInterval(CP.getSrcReg()); @@ -966,8 +943,8 @@ bool SimpleRegisterCoalescing::shouldJoinPhys(CoalescerPair &CP) { /// isWinToJoinCrossClass - Return true if it's profitable to coalesce /// two virtual registers from different register classes. bool -SimpleRegisterCoalescing::isWinToJoinCrossClass(unsigned SrcReg, - unsigned DstReg, +RegisterCoalescer::isWinToJoinCrossClass(unsigned SrcReg, + unsigned DstReg, const TargetRegisterClass *SrcRC, const TargetRegisterClass *DstRC, const TargetRegisterClass *NewRC) { @@ -1019,7 +996,7 @@ SimpleRegisterCoalescing::isWinToJoinCrossClass(unsigned SrcReg, /// if the copy was successfully coalesced away. If it is not currently /// possible to coalesce this interval, but it may be possible if other /// things get coalesced, then it returns true by reference in 'Again'. -bool SimpleRegisterCoalescing::JoinCopy(MachineInstr *CopyMI, bool &Again) { +bool RegisterCoalescer::JoinCopy(MachineInstr *CopyMI, bool &Again) { Again = false; if (JoinedCopies.count(CopyMI) || ReMatCopies.count(CopyMI)) @@ -1211,7 +1188,7 @@ static unsigned ComputeUltimateVN(VNInfo *VNI, /// JoinIntervals - Attempt to join these two intervals. On failure, this /// returns false. -bool SimpleRegisterCoalescing::JoinIntervals(CoalescerPair &CP) { +bool RegisterCoalescer::JoinIntervals(CoalescerPair &CP) { LiveInterval &RHS = li_->getInterval(CP.getSrcReg()); DEBUG({ dbgs() << "\t\tRHS = "; RHS.print(dbgs(), tri_); dbgs() << "\n"; }); @@ -1446,7 +1423,7 @@ namespace { }; } -void SimpleRegisterCoalescing::CopyCoalesceInMBB(MachineBasicBlock *MBB, +void RegisterCoalescer::CopyCoalesceInMBB(MachineBasicBlock *MBB, std::vector &TryAgain) { DEBUG(dbgs() << MBB->getName() << ":\n"); @@ -1504,7 +1481,7 @@ void SimpleRegisterCoalescing::CopyCoalesceInMBB(MachineBasicBlock *MBB, } } -void SimpleRegisterCoalescing::joinIntervals() { +void RegisterCoalescer::joinIntervals() { DEBUG(dbgs() << "********** JOINING INTERVALS ***********\n"); std::vector TryAgainList; @@ -1555,13 +1532,13 @@ void SimpleRegisterCoalescing::joinIntervals() { } } -void SimpleRegisterCoalescing::releaseMemory() { +void RegisterCoalescer::releaseMemory() { JoinedCopies.clear(); ReMatCopies.clear(); ReMatDefs.clear(); } -bool SimpleRegisterCoalescing::runOnMachineFunction(MachineFunction &fn) { +bool RegisterCoalescer::runOnMachineFunction(MachineFunction &fn) { mf_ = &fn; mri_ = &fn.getRegInfo(); tm_ = &fn.getTarget(); @@ -1706,13 +1683,10 @@ bool SimpleRegisterCoalescing::runOnMachineFunction(MachineFunction &fn) { } /// print - Implement the dump method. -void SimpleRegisterCoalescing::print(raw_ostream &O, const Module* m) const { +void RegisterCoalescer::print(raw_ostream &O, const Module* m) const { li_->print(O, m); } -RegisterCoalescer* llvm::createSimpleRegisterCoalescer() { - return new SimpleRegisterCoalescing(); +RegisterCoalescer *llvm::createRegisterCoalescer() { + return new RegisterCoalescer(); } - -// Make sure that anything that uses RegisterCoalescer pulls in this file... -DEFINING_FILE_FOR(SimpleRegisterCoalescing) diff --git a/lib/CodeGen/RegisterCoalescer.h b/lib/CodeGen/RegisterCoalescer.h index 739a4c3..ec83b81 100644 --- a/lib/CodeGen/RegisterCoalescer.h +++ b/lib/CodeGen/RegisterCoalescer.h @@ -29,24 +29,126 @@ namespace llvm { class TargetRegisterInfo; class TargetRegisterClass; class TargetInstrInfo; - class SimpleRegisterCoalescing; class LiveDebugVariables; class VirtRegMap; class MachineLoopInfo; + class CoalescerPair; + /// An abstract interface for register coalescers. Coalescers must /// implement this interface to be part of the coalescer analysis /// group. - class RegisterCoalescer { + class RegisterCoalescer : public MachineFunctionPass { + MachineFunction* mf_; + MachineRegisterInfo* mri_; + const TargetMachine* tm_; + const TargetRegisterInfo* tri_; + const TargetInstrInfo* tii_; + LiveIntervals *li_; + LiveDebugVariables *ldv_; + const MachineLoopInfo* loopInfo; + AliasAnalysis *AA; + RegisterClassInfo RegClassInfo; + + /// JoinedCopies - Keep track of copies eliminated due to coalescing. + /// + SmallPtrSet JoinedCopies; + + /// ReMatCopies - Keep track of copies eliminated due to remat. + /// + SmallPtrSet ReMatCopies; + + /// ReMatDefs - Keep track of definition instructions which have + /// been remat'ed. + SmallPtrSet ReMatDefs; + + /// joinIntervals - join compatible live intervals + void joinIntervals(); + + /// CopyCoalesceInMBB - Coalesce copies in the specified MBB, putting + /// copies that cannot yet be coalesced into the "TryAgain" list. + void CopyCoalesceInMBB(MachineBasicBlock *MBB, + std::vector &TryAgain); + + /// JoinCopy - Attempt to join intervals corresponding to SrcReg/DstReg, + /// which are the src/dst of the copy instruction CopyMI. This returns true + /// if the copy was successfully coalesced away. If it is not currently + /// possible to coalesce this interval, but it may be possible if other + /// things get coalesced, then it returns true by reference in 'Again'. + bool JoinCopy(MachineInstr *TheCopy, bool &Again); + + /// JoinIntervals - Attempt to join these two intervals. On failure, this + /// returns false. The output "SrcInt" will not have been modified, so we can + /// use this information below to update aliases. + bool JoinIntervals(CoalescerPair &CP); + + /// AdjustCopiesBackFrom - We found a non-trivially-coalescable copy. If + /// the source value number is defined by a copy from the destination reg + /// see if we can merge these two destination reg valno# into a single + /// value number, eliminating a copy. + bool AdjustCopiesBackFrom(const CoalescerPair &CP, MachineInstr *CopyMI); + + /// HasOtherReachingDefs - Return true if there are definitions of IntB + /// other than BValNo val# that can reach uses of AValno val# of IntA. + bool HasOtherReachingDefs(LiveInterval &IntA, LiveInterval &IntB, + VNInfo *AValNo, VNInfo *BValNo); + + /// RemoveCopyByCommutingDef - We found a non-trivially-coalescable copy. + /// If the source value number is defined by a commutable instruction and + /// its other operand is coalesced to the copy dest register, see if we + /// can transform the copy into a noop by commuting the definition. + bool RemoveCopyByCommutingDef(const CoalescerPair &CP,MachineInstr *CopyMI); + + /// ReMaterializeTrivialDef - If the source of a copy is defined by a trivial + /// computation, replace the copy by rematerialize the definition. + /// If PreserveSrcInt is true, make sure SrcInt is valid after the call. + bool ReMaterializeTrivialDef(LiveInterval &SrcInt, bool PreserveSrcInt, + unsigned DstReg, unsigned DstSubIdx, + MachineInstr *CopyMI); + + /// shouldJoinPhys - Return true if a physreg copy should be joined. + bool shouldJoinPhys(CoalescerPair &CP); + + /// isWinToJoinCrossClass - Return true if it's profitable to coalesce + /// two virtual registers from different register classes. + bool isWinToJoinCrossClass(unsigned SrcReg, + unsigned DstReg, + const TargetRegisterClass *SrcRC, + const TargetRegisterClass *DstRC, + const TargetRegisterClass *NewRC); + + /// UpdateRegDefsUses - Replace all defs and uses of SrcReg to DstReg and + /// update the subregister number if it is not zero. If DstReg is a + /// physical register and the existing subregister number of the def / use + /// being updated is not zero, make sure to set it to the correct physical + /// subregister. + void UpdateRegDefsUses(const CoalescerPair &CP); + + /// RemoveDeadDef - If a def of a live interval is now determined dead, + /// remove the val# it defines. If the live interval becomes empty, remove + /// it as well. + bool RemoveDeadDef(LiveInterval &li, MachineInstr *DefMI); + + /// RemoveCopyFlag - If DstReg is no longer defined by CopyMI, clear the + /// VNInfo copy flag for DstReg and all aliases. + void RemoveCopyFlag(unsigned DstReg, const MachineInstr *CopyMI); + + /// markAsJoined - Remember that CopyMI has already been joined. + void markAsJoined(MachineInstr *CopyMI); + public: static char ID; // Class identification, replacement for typeinfo - RegisterCoalescer() {} - virtual ~RegisterCoalescer(); // We want to be subclassed + RegisterCoalescer() : MachineFunctionPass(ID) { + initializeRegisterCoalescerPass(*PassRegistry::getPassRegistry()); + } /// Run the coalescer on this function, providing interference /// data to query. Return whether we removed any copies. virtual bool coalesceFunction(MachineFunction &mf, - RegallocQuery &ifd) = 0; + RegallocQuery &ifd) { + // This runs as an independent pass, so don't do anything. + return false; + } /// Reset state. Can be used to allow a coalescer run by /// PassManager to be run again by the register allocator. @@ -59,8 +161,16 @@ namespace llvm { /// which to invalidate when running the register allocator or any /// pass that might call coalescing. The long-term solution is to /// allow hierarchies of PassManagers. - virtual void getAnalysisUsage(AnalysisUsage &AU) const {} - }; + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + + virtual void releaseMemory(); + + /// runOnMachineFunction - pass entry point + virtual bool runOnMachineFunction(MachineFunction&); + + /// print - Implement the dump method. + virtual void print(raw_ostream &O, const Module* = 0) const; + }; /// An abstract interface for register allocators to interact with /// coalescers @@ -82,7 +192,7 @@ namespace llvm { /// /// allocation doesn't pre-compute interference information it's /// /// the best we can do. Coalescers are always free to ignore this /// /// and implement their own discovery strategy. See - /// /// SimpleRegisterCoalescing for an example. + /// /// RegisterCoalescer for an example. /// void getInterferences(IntervalSet &interferences, /// const LiveInterval &a) const { /// for(LiveIntervals::const_iterator iv = li.begin(), @@ -236,135 +346,6 @@ namespace llvm { /// getNewRC - Return the register class of the coalesced register. const TargetRegisterClass *getNewRC() const { return newRC_; } }; - - class SimpleRegisterCoalescing : public MachineFunctionPass, - public RegisterCoalescer { - MachineFunction* mf_; - MachineRegisterInfo* mri_; - const TargetMachine* tm_; - const TargetRegisterInfo* tri_; - const TargetInstrInfo* tii_; - LiveIntervals *li_; - LiveDebugVariables *ldv_; - const MachineLoopInfo* loopInfo; - AliasAnalysis *AA; - RegisterClassInfo RegClassInfo; - - /// JoinedCopies - Keep track of copies eliminated due to coalescing. - /// - SmallPtrSet JoinedCopies; - - /// ReMatCopies - Keep track of copies eliminated due to remat. - /// - SmallPtrSet ReMatCopies; - - /// ReMatDefs - Keep track of definition instructions which have - /// been remat'ed. - SmallPtrSet ReMatDefs; - - public: - static char ID; // Pass identifcation, replacement for typeid - SimpleRegisterCoalescing() : MachineFunctionPass(ID) { - initializeSimpleRegisterCoalescingPass(*PassRegistry::getPassRegistry()); - } - - virtual void getAnalysisUsage(AnalysisUsage &AU) const; - virtual void releaseMemory(); - - /// runOnMachineFunction - pass entry point - virtual bool runOnMachineFunction(MachineFunction&); - - bool coalesceFunction(MachineFunction &mf, RegallocQuery &) { - // This runs as an independent pass, so don't do anything. - return false; - } - - /// print - Implement the dump method. - virtual void print(raw_ostream &O, const Module* = 0) const; - - private: - /// joinIntervals - join compatible live intervals - void joinIntervals(); - - /// CopyCoalesceInMBB - Coalesce copies in the specified MBB, putting - /// copies that cannot yet be coalesced into the "TryAgain" list. - void CopyCoalesceInMBB(MachineBasicBlock *MBB, - std::vector &TryAgain); - - /// JoinCopy - Attempt to join intervals corresponding to SrcReg/DstReg, - /// which are the src/dst of the copy instruction CopyMI. This returns true - /// if the copy was successfully coalesced away. If it is not currently - /// possible to coalesce this interval, but it may be possible if other - /// things get coalesced, then it returns true by reference in 'Again'. - bool JoinCopy(MachineInstr *TheCopy, bool &Again); - - /// JoinIntervals - Attempt to join these two intervals. On failure, this - /// returns false. The output "SrcInt" will not have been modified, so we can - /// use this information below to update aliases. - bool JoinIntervals(CoalescerPair &CP); - - /// AdjustCopiesBackFrom - We found a non-trivially-coalescable copy. If - /// the source value number is defined by a copy from the destination reg - /// see if we can merge these two destination reg valno# into a single - /// value number, eliminating a copy. - bool AdjustCopiesBackFrom(const CoalescerPair &CP, MachineInstr *CopyMI); - - /// HasOtherReachingDefs - Return true if there are definitions of IntB - /// other than BValNo val# that can reach uses of AValno val# of IntA. - bool HasOtherReachingDefs(LiveInterval &IntA, LiveInterval &IntB, - VNInfo *AValNo, VNInfo *BValNo); - - /// RemoveCopyByCommutingDef - We found a non-trivially-coalescable copy. - /// If the source value number is defined by a commutable instruction and - /// its other operand is coalesced to the copy dest register, see if we - /// can transform the copy into a noop by commuting the definition. - bool RemoveCopyByCommutingDef(const CoalescerPair &CP,MachineInstr *CopyMI); - - /// ReMaterializeTrivialDef - If the source of a copy is defined by a trivial - /// computation, replace the copy by rematerialize the definition. - /// If PreserveSrcInt is true, make sure SrcInt is valid after the call. - bool ReMaterializeTrivialDef(LiveInterval &SrcInt, bool PreserveSrcInt, - unsigned DstReg, unsigned DstSubIdx, - MachineInstr *CopyMI); - - /// shouldJoinPhys - Return true if a physreg copy should be joined. - bool shouldJoinPhys(CoalescerPair &CP); - - /// isWinToJoinCrossClass - Return true if it's profitable to coalesce - /// two virtual registers from different register classes. - bool isWinToJoinCrossClass(unsigned SrcReg, - unsigned DstReg, - const TargetRegisterClass *SrcRC, - const TargetRegisterClass *DstRC, - const TargetRegisterClass *NewRC); - - /// UpdateRegDefsUses - Replace all defs and uses of SrcReg to DstReg and - /// update the subregister number if it is not zero. If DstReg is a - /// physical register and the existing subregister number of the def / use - /// being updated is not zero, make sure to set it to the correct physical - /// subregister. - void UpdateRegDefsUses(const CoalescerPair &CP); - - /// RemoveDeadDef - If a def of a live interval is now determined dead, - /// remove the val# it defines. If the live interval becomes empty, remove - /// it as well. - bool RemoveDeadDef(LiveInterval &li, MachineInstr *DefMI); - - /// RemoveCopyFlag - If DstReg is no longer defined by CopyMI, clear the - /// VNInfo copy flag for DstReg and all aliases. - void RemoveCopyFlag(unsigned DstReg, const MachineInstr *CopyMI); - - /// markAsJoined - Remember that CopyMI has already been joined. - void markAsJoined(MachineInstr *CopyMI); - }; } // End llvm namespace -// Because of the way .a files work, we must force the SimpleRC -// implementation to be pulled in if the RegisterCoalescing header is -// included. Otherwise we run the risk of RegisterCoalescing being -// used, but the default implementation not being linked into the tool -// that uses it. -FORCE_DEFINING_FILE_TO_BE_LINKED(RegisterCoalescer) -FORCE_DEFINING_FILE_TO_BE_LINKED(SimpleRegisterCoalescing) - #endif diff --git a/lib/CodeGen/SplitKit.cpp b/lib/CodeGen/SplitKit.cpp index bf27cc8..18f315a 100644 --- a/lib/CodeGen/SplitKit.cpp +++ b/lib/CodeGen/SplitKit.cpp @@ -122,7 +122,7 @@ void SplitAnalysis::analyzeUses() { // Compute per-live block info. if (!calcLiveBlockInfo()) { // FIXME: calcLiveBlockInfo found inconsistencies in the live range. - // I am looking at you, SimpleRegisterCoalescing! + // I am looking at you, RegisterCoalescer! DidRepairRange = true; ++NumRepairs; DEBUG(dbgs() << "*** Fixing inconsistent live interval! ***\n"); @@ -165,7 +165,7 @@ bool SplitAnalysis::calcLiveBlockInfo() { tie(Start, Stop) = LIS.getSlotIndexes()->getMBBRange(BI.MBB); // If the block contains no uses, the range must be live through. At one - // point, SimpleRegisterCoalescing could create dangling ranges that ended + // point, RegisterCoalescer could create dangling ranges that ended // mid-block. if (UseI == UseE || *UseI >= Stop) { ++NumThroughBlocks; -- cgit v1.1 From ca08dcc4834341e44abf02b92a67ac7d1a708e1d Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Sun, 26 Jun 2011 22:44:34 +0000 Subject: Remove unused methods. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133900 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/RegisterCoalescer.h | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/lib/CodeGen/RegisterCoalescer.h b/lib/CodeGen/RegisterCoalescer.h index ec83b81..2e8a8ae 100644 --- a/lib/CodeGen/RegisterCoalescer.h +++ b/lib/CodeGen/RegisterCoalescer.h @@ -142,18 +142,6 @@ namespace llvm { initializeRegisterCoalescerPass(*PassRegistry::getPassRegistry()); } - /// Run the coalescer on this function, providing interference - /// data to query. Return whether we removed any copies. - virtual bool coalesceFunction(MachineFunction &mf, - RegallocQuery &ifd) { - // This runs as an independent pass, so don't do anything. - return false; - } - - /// Reset state. Can be used to allow a coalescer run by - /// PassManager to be run again by the register allocator. - virtual void reset(MachineFunction &mf) {} - /// Register allocators must call this from their own /// getAnalysisUsage to cover the case where the coalescer is not /// a Pass in the proper sense and isn't managed by PassManager. @@ -220,7 +208,6 @@ namespace llvm { /// // We don't reset the coalescer so if it's already been run this /// // takes almost no time. /// LinearScanRegallocQuery ifd(*li_); - /// coalescer.coalesceFunction(fn, ifd); /// class RegallocQuery { public: -- cgit v1.1 From 7a2ecd3f99ae4dede7e8c1984c2a08984be69363 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Mon, 27 Jun 2011 04:08:29 +0000 Subject: Decode and pretty print inline asm operand descriptors. The INLINEASM MachineInstrs have an immediate operand describing each original inline asm operand. Decode the bits in MachineInstr::print() so it is easier to read: INLINEASM , $0:[regdef], %vreg0, %vreg1, $1:[imm], 1, $2:[reguse] [tiedto:$0], %vreg2, %vreg3, $3:[regdef-ec], %EFLAGS git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133901 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MachineInstr.cpp | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/lib/CodeGen/MachineInstr.cpp b/lib/CodeGen/MachineInstr.cpp index e423e3f..d4d8202 100644 --- a/lib/CodeGen/MachineInstr.cpp +++ b/lib/CodeGen/MachineInstr.cpp @@ -1367,6 +1367,8 @@ void MachineInstr::print(raw_ostream &OS, const TargetMachine *TM) const { // Print the rest of the operands. bool OmittedAnyCallClobbers = false; bool FirstOp = true; + unsigned AsmDescOp = ~0u; + unsigned AsmOpCount = 0; if (isInlineAsm()) { // Print asm string. @@ -1380,7 +1382,7 @@ void MachineInstr::print(raw_ostream &OS, const TargetMachine *TM) const { if (ExtraInfo & InlineAsm::Extra_IsAlignStack) OS << " [alignstack]"; - StartOp = InlineAsm::MIOp_FirstOperand; + StartOp = AsmDescOp = InlineAsm::MIOp_FirstOperand; FirstOp = false; } @@ -1434,6 +1436,25 @@ void MachineInstr::print(raw_ostream &OS, const TargetMachine *TM) const { MO.print(OS, TM); } else if (TM && (isInsertSubreg() || isRegSequence()) && MO.isImm()) { OS << TM->getRegisterInfo()->getSubRegIndexName(MO.getImm()); + } else if (i == AsmDescOp && MO.isImm()) { + // Pretty print the inline asm operand descriptor. + OS << '$' << AsmOpCount++; + unsigned Flag = MO.getImm(); + switch (InlineAsm::getKind(Flag)) { + case InlineAsm::Kind_RegUse: OS << ":[reguse]"; break; + case InlineAsm::Kind_RegDef: OS << ":[regdef]"; break; + case InlineAsm::Kind_Imm: OS << ":[imm]"; break; + case InlineAsm::Kind_Mem: OS << ":[mem]"; break; + case InlineAsm::Kind_RegDefEarlyClobber: OS << ":[regdef-ec]"; break; + default: OS << ":[??" << InlineAsm::getKind(Flag) << ']'; break; + } + + unsigned TiedTo = 0; + if (InlineAsm::isUseOperandTiedToDef(Flag, TiedTo)) + OS << " [tiedto:$" << TiedTo << ']'; + + // Compute the index of the next operand descriptor. + AsmDescOp += 1 + InlineAsm::getNumOperandRegisters(Flag); } else MO.print(OS, TM); } -- cgit v1.1 From f792fa90f1125553008659c743cba85b9b5d2e5e Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Mon, 27 Jun 2011 04:08:33 +0000 Subject: Distinguish early clobber output operands from clobbered registers. Both become defs on the INLINEASM MachineInstr, but we now use two different asm operand kinds. The new Kind_Clobber is treated identically to the old Kind_RegDefEarlyClobber for now, but x87 floating point stack inline assembly does care about the difference. This will pop a register off the stack: asm("fstp %st" : : "t"(x) : "st"); While this will pop the input and push an output: asm("fst %st" : "=&t"(r) : "t"(x)); We need to know if ST0 was a clobber or an output operand, and we can't depend on flags for that. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133902 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/InlineAsm.h | 26 ++++++++++++++++-------- lib/CodeGen/MachineInstr.cpp | 3 ++- lib/CodeGen/SelectionDAG/InstrEmitter.cpp | 1 + lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp | 3 ++- lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp | 3 ++- lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 3 +-- 6 files changed, 26 insertions(+), 13 deletions(-) diff --git a/include/llvm/InlineAsm.h b/include/llvm/InlineAsm.h index 0d86086..ed5bf8b 100644 --- a/include/llvm/InlineAsm.h +++ b/include/llvm/InlineAsm.h @@ -188,25 +188,32 @@ public: // in the backend. enum { + // Fixed operands on an INLINEASM SDNode. Op_InputChain = 0, Op_AsmString = 1, Op_MDNode = 2, Op_ExtraInfo = 3, // HasSideEffects, IsAlignStack Op_FirstOperand = 4, + // Fixed operands on an INLINEASM MachineInstr. MIOp_AsmString = 0, MIOp_ExtraInfo = 1, // HasSideEffects, IsAlignStack MIOp_FirstOperand = 2, + // Interpretation of the MIOp_ExtraInfo bit field. Extra_HasSideEffects = 1, Extra_IsAlignStack = 2, - - Kind_RegUse = 1, - Kind_RegDef = 2, - Kind_Imm = 3, - Kind_Mem = 4, - Kind_RegDefEarlyClobber = 6, - + + // Inline asm operands map to multiple SDNode / MachineInstr operands. + // The first operand is an immediate describing the asm operand, the low + // bits is the kind: + Kind_RegUse = 1, // Input register, "r". + Kind_RegDef = 2, // Output register, "=r". + Kind_RegDefEarlyClobber = 3, // Early-clobber output register, "=&r". + Kind_Clobber = 4, // Clobbered register, "~r". + Kind_Imm = 5, // Immediate. + Kind_Mem = 6, // Memory operand, "m". + Flag_MatchingOperand = 0x80000000 }; @@ -233,7 +240,10 @@ public: static bool isRegDefEarlyClobberKind(unsigned Flag) { return getKind(Flag) == Kind_RegDefEarlyClobber; } - + static bool isClobberKind(unsigned Flag) { + return getKind(Flag) == Kind_Clobber; + } + /// getNumOperandRegisters - Extract the number of registers field from the /// inline asm operand flag. static unsigned getNumOperandRegisters(unsigned Flag) { diff --git a/lib/CodeGen/MachineInstr.cpp b/lib/CodeGen/MachineInstr.cpp index d4d8202..938b83d 100644 --- a/lib/CodeGen/MachineInstr.cpp +++ b/lib/CodeGen/MachineInstr.cpp @@ -1443,9 +1443,10 @@ void MachineInstr::print(raw_ostream &OS, const TargetMachine *TM) const { switch (InlineAsm::getKind(Flag)) { case InlineAsm::Kind_RegUse: OS << ":[reguse]"; break; case InlineAsm::Kind_RegDef: OS << ":[regdef]"; break; + case InlineAsm::Kind_RegDefEarlyClobber: OS << ":[regdef-ec]"; break; + case InlineAsm::Kind_Clobber: OS << ":[clobber]"; break; case InlineAsm::Kind_Imm: OS << ":[imm]"; break; case InlineAsm::Kind_Mem: OS << ":[mem]"; break; - case InlineAsm::Kind_RegDefEarlyClobber: OS << ":[regdef-ec]"; break; default: OS << ":[??" << InlineAsm::getKind(Flag) << ']'; break; } diff --git a/lib/CodeGen/SelectionDAG/InstrEmitter.cpp b/lib/CodeGen/SelectionDAG/InstrEmitter.cpp index 3c6a46e..e8c9c51 100644 --- a/lib/CodeGen/SelectionDAG/InstrEmitter.cpp +++ b/lib/CodeGen/SelectionDAG/InstrEmitter.cpp @@ -851,6 +851,7 @@ EmitSpecialNode(SDNode *Node, bool IsClone, bool IsCloned, } break; case InlineAsm::Kind_RegDefEarlyClobber: + case InlineAsm::Kind_Clobber: for (; NumVals; --NumVals, ++i) { unsigned Reg = cast(Node->getOperand(i))->getReg(); MI->addOperand(MachineOperand::CreateReg(Reg, /*isDef=*/ true, diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp index 7b560d1..6bed1db 100644 --- a/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp +++ b/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp @@ -490,7 +490,8 @@ bool ScheduleDAGFast::DelayForLiveRegsBottomUp(SUnit *SU, ++i; // Skip the ID value. if (InlineAsm::isRegDefKind(Flags) || - InlineAsm::isRegDefEarlyClobberKind(Flags)) { + InlineAsm::isRegDefEarlyClobberKind(Flags) || + InlineAsm::isClobberKind(Flags)) { // Check for def of register or earlyclobber register. for (; NumVals; --NumVals, ++i) { unsigned Reg = cast(Node->getOperand(i))->getReg(); diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp index a827187..1053b88 100644 --- a/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp +++ b/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp @@ -1092,7 +1092,8 @@ DelayForLiveRegsBottomUp(SUnit *SU, SmallVector &LRegs) { ++i; // Skip the ID value. if (InlineAsm::isRegDefKind(Flags) || - InlineAsm::isRegDefEarlyClobberKind(Flags)) { + InlineAsm::isRegDefEarlyClobberKind(Flags) || + InlineAsm::isClobberKind(Flags)) { // Check for def of register or earlyclobber register. for (; NumVals; --NumVals, ++i) { unsigned Reg = cast(Node->getOperand(i))->getReg(); diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 19bfa33..3001206 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -6051,8 +6051,7 @@ void SelectionDAGBuilder::visitInlineAsm(ImmutableCallSite CS) { // Add the clobbered value to the operand list, so that the register // allocator is aware that the physreg got clobbered. if (!OpInfo.AssignedRegs.Regs.empty()) - OpInfo.AssignedRegs.AddInlineAsmOperands( - InlineAsm::Kind_RegDefEarlyClobber, + OpInfo.AssignedRegs.AddInlineAsmOperands(InlineAsm::Kind_Clobber, false, 0, DAG, AsmNodeOperands); break; -- cgit v1.1 From 1baeb006d2bb74dd9f6fa633fcc53e3b1ecbbf35 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Mon, 27 Jun 2011 04:08:36 +0000 Subject: Grow the X86FloatingPoint register map to hold 16 registers. This allows for more live scratch registers which is needed to handle live ST registers before return and inline asm instructions. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133903 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86FloatingPoint.cpp | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/lib/Target/X86/X86FloatingPoint.cpp b/lib/Target/X86/X86FloatingPoint.cpp index 325d061..e16f217 100644 --- a/lib/Target/X86/X86FloatingPoint.cpp +++ b/lib/Target/X86/X86FloatingPoint.cpp @@ -126,10 +126,20 @@ namespace { void bundleCFG(MachineFunction &MF); MachineBasicBlock *MBB; // Current basic block + + // The hardware keeps track of how many FP registers are live, so we have + // to model that exactly. Usually, each live register corresponds to an + // FP register, but when dealing with calls, returns, and inline + // assembly, it is sometimes neccesary to have live scratch registers. unsigned Stack[8]; // FP Registers in each stack slot... - unsigned RegMap[8]; // Track which stack slot contains each register unsigned StackTop; // The current top of the FP stack. + // For each live FP register, point to its Stack[] entry. + // The first entries correspond to FP0-FP6, the rest are scratch registers + // used when we need slightly different live registers than what the + // register allocator thinks. + unsigned RegMap[16]; + // Set up our stack model to match the incoming registers to MBB. void setupBlockStack(); @@ -148,7 +158,7 @@ namespace { /// getSlot - Return the stack slot number a particular register number is /// in. unsigned getSlot(unsigned RegNo) const { - assert(RegNo < 8 && "Regno out of range!"); + assert(RegNo < array_lengthof(RegMap) && "Regno out of range!"); return RegMap[RegNo]; } @@ -160,7 +170,7 @@ namespace { /// getScratchReg - Return an FP register that is not currently in use. unsigned getScratchReg() { - for (int i = 7; i >= 0; --i) + for (int i = array_lengthof(RegMap) - 1; i >= 8; --i) if (!isLive(i)) return i; llvm_unreachable("Ran out of scratch FP registers"); @@ -181,7 +191,7 @@ namespace { // pushReg - Push the specified FP register onto the stack. void pushReg(unsigned Reg) { - assert(Reg < 8 && "Register number out of range!"); + assert(Reg < array_lengthof(RegMap) && "Register number out of range!"); if (StackTop >= 8) report_fatal_error("Stack overflow!"); Stack[StackTop] = Reg; @@ -236,7 +246,7 @@ namespace { /// Adjust the live registers to be the set in Mask. void adjustLiveRegs(unsigned Mask, MachineBasicBlock::iterator I); - /// Shuffle the top FixCount stack entries susch that FP reg FixStack[0] is + /// Shuffle the top FixCount stack entries such that FP reg FixStack[0] is /// st(0), FP reg FixStack[1] is st(1) etc. void shuffleStackTop(const unsigned char *FixStack, unsigned FixCount, MachineBasicBlock::iterator I); -- cgit v1.1 From 99e0b2a8df7e3a49c0e1edd250d17604fe2fb21c Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Mon, 27 Jun 2011 04:20:45 +0000 Subject: Move onlyUsedByLifetimeMarkers to ValueTracking so that it can be used by other passes as well. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133904 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Analysis/ValueTracking.h | 4 ++++ lib/Analysis/ValueTracking.cpp | 16 ++++++++++++++++ lib/Transforms/Utils/PromoteMemoryToRegister.cpp | 17 +---------------- 3 files changed, 21 insertions(+), 16 deletions(-) diff --git a/include/llvm/Analysis/ValueTracking.h b/include/llvm/Analysis/ValueTracking.h index 6df1693..d4354bb 100644 --- a/include/llvm/Analysis/ValueTracking.h +++ b/include/llvm/Analysis/ValueTracking.h @@ -158,6 +158,10 @@ namespace llvm { return GetUnderlyingObject(const_cast(V), TD, MaxLookup); } + /// onlyUsedByLifetimeMarkers - Return true if the only users of this pointer + /// are lifetime markers. + bool onlyUsedByLifetimeMarkers(const Value *V); + } // end namespace llvm #endif diff --git a/lib/Analysis/ValueTracking.cpp b/lib/Analysis/ValueTracking.cpp index dab5aeb..130e3ce 100644 --- a/lib/Analysis/ValueTracking.cpp +++ b/lib/Analysis/ValueTracking.cpp @@ -1783,3 +1783,19 @@ llvm::GetUnderlyingObject(Value *V, const TargetData *TD, unsigned MaxLookup) { } return V; } + +/// onlyUsedByLifetimeMarkers - Return true if the only users of this pointer +/// are lifetime markers. +/// +bool llvm::onlyUsedByLifetimeMarkers(const Value *V) { + for (Value::const_use_iterator UI = V->use_begin(), UE = V->use_end(); + UI != UE; ++UI) { + const IntrinsicInst *II = dyn_cast(*UI); + if (!II) return false; + + if (II->getIntrinsicID() != Intrinsic::lifetime_start && + II->getIntrinsicID() != Intrinsic::lifetime_end) + return false; + } + return true; +} diff --git a/lib/Transforms/Utils/PromoteMemoryToRegister.cpp b/lib/Transforms/Utils/PromoteMemoryToRegister.cpp index 32d1dcc..e5a00f4 100644 --- a/lib/Transforms/Utils/PromoteMemoryToRegister.cpp +++ b/lib/Transforms/Utils/PromoteMemoryToRegister.cpp @@ -38,6 +38,7 @@ #include "llvm/Analysis/DIBuilder.h" #include "llvm/Analysis/Dominators.h" #include "llvm/Analysis/InstructionSimplify.h" +#include "llvm/Analysis/ValueTracking.h" #include "llvm/Transforms/Utils/Local.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" @@ -73,22 +74,6 @@ struct DenseMapInfo > { }; } -/// onlyUsedByLifetimeMarkers - Return true if the only users of this pointer -/// are lifetime markers. -/// -static bool onlyUsedByLifetimeMarkers(const Value *V) { - for (Value::const_use_iterator UI = V->use_begin(), UE = V->use_end(); - UI != UE; ++UI) { - const IntrinsicInst *II = dyn_cast(*UI); - if (!II) return false; - - if (II->getIntrinsicID() != Intrinsic::lifetime_start && - II->getIntrinsicID() != Intrinsic::lifetime_end) - return false; - } - return true; -} - /// isAllocaPromotable - Return true if this alloca is legal for promotion. /// This is true if there are only loads and stores to the alloca. /// -- cgit v1.1 From 9174d5c7383490d79b6a483d73cded54e32275d6 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Mon, 27 Jun 2011 05:40:02 +0000 Subject: Teach one piece of scalarrepl to handle lifetime markers. When transforming an alloca that only holds a copy of a global and we're going to replace the users of the alloca with that global, just nuke the lifetime intrinsics. Part of PR10121. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133905 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Scalar/ScalarReplAggregates.cpp | 50 ++++++++++++++++++------ test/Transforms/ScalarRepl/memcpy-from-global.ll | 14 +++++++ 2 files changed, 51 insertions(+), 13 deletions(-) diff --git a/lib/Transforms/Scalar/ScalarReplAggregates.cpp b/lib/Transforms/Scalar/ScalarReplAggregates.cpp index 46ac948..6fa3627 100644 --- a/lib/Transforms/Scalar/ScalarReplAggregates.cpp +++ b/lib/Transforms/Scalar/ScalarReplAggregates.cpp @@ -152,7 +152,8 @@ namespace { void RewriteLoadUserOfWholeAlloca(LoadInst *LI, AllocaInst *AI, SmallVector &NewElts); - static MemTransferInst *isOnlyCopiedFromConstantGlobal(AllocaInst *AI); + static MemTransferInst *isOnlyCopiedFromConstantGlobal( + AllocaInst *AI, SmallVector &ToDelete); }; // SROA_DT - SROA that uses DominatorTree. @@ -1443,8 +1444,8 @@ static bool ShouldAttemptScalarRepl(AllocaInst *AI) { // performScalarRepl - This algorithm is a simple worklist driven algorithm, -// which runs on all of the malloc/alloca instructions in the function, removing -// them if they are only used by getelementptr instructions. +// which runs on all of the alloca instructions in the function, removing them +// if they are only used by getelementptr instructions. // bool SROA::performScalarRepl(Function &F) { std::vector WorkList; @@ -1478,12 +1479,15 @@ bool SROA::performScalarRepl(Function &F) { // the constant global instead. This is commonly produced by the CFE by // constructs like "void foo() { int A[] = {1,2,3,4,5,6,7,8,9...}; }" if 'A' // is only subsequently read. - if (MemTransferInst *TheCopy = isOnlyCopiedFromConstantGlobal(AI)) { + SmallVector ToDelete; + if (MemTransferInst *Copy = isOnlyCopiedFromConstantGlobal(AI, ToDelete)) { DEBUG(dbgs() << "Found alloca equal to global: " << *AI << '\n'); - DEBUG(dbgs() << " memcpy = " << *TheCopy << '\n'); - Constant *TheSrc = cast(TheCopy->getSource()); + DEBUG(dbgs() << " memcpy = " << *Copy << '\n'); + for (unsigned i = 0, e = ToDelete.size(); i != e; ++i) + ToDelete[i]->eraseFromParent(); + Constant *TheSrc = cast(Copy->getSource()); AI->replaceAllUsesWith(ConstantExpr::getBitCast(TheSrc, AI->getType())); - TheCopy->eraseFromParent(); // Don't mutate the global. + Copy->eraseFromParent(); // Don't mutate the global. AI->eraseFromParent(); ++NumGlobals; Changed = true; @@ -2507,8 +2511,14 @@ static bool PointsToConstantGlobal(Value *V) { /// the uses. If we see a memcpy/memmove that targets an unoffseted pointer to /// the alloca, and if the source pointer is a pointer to a constant global, we /// can optimize this. -static bool isOnlyCopiedFromConstantGlobal(Value *V, MemTransferInst *&TheCopy, - bool isOffset) { +static bool +isOnlyCopiedFromConstantGlobal(Value *V, MemTransferInst *&TheCopy, + bool isOffset, + SmallVector &LifetimeMarkers) { + // We track lifetime intrinsics as we encounter them. If we decide to go + // ahead and replace the value with the global, this lets the caller quickly + // eliminate the markers. + for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI!=E; ++UI) { User *U = cast(*UI); @@ -2520,7 +2530,8 @@ static bool isOnlyCopiedFromConstantGlobal(Value *V, MemTransferInst *&TheCopy, if (BitCastInst *BCI = dyn_cast(U)) { // If uses of the bitcast are ok, we are ok. - if (!isOnlyCopiedFromConstantGlobal(BCI, TheCopy, isOffset)) + if (!isOnlyCopiedFromConstantGlobal(BCI, TheCopy, isOffset, + LifetimeMarkers)) return false; continue; } @@ -2528,7 +2539,8 @@ static bool isOnlyCopiedFromConstantGlobal(Value *V, MemTransferInst *&TheCopy, // If the GEP has all zero indices, it doesn't offset the pointer. If it // doesn't, it does. if (!isOnlyCopiedFromConstantGlobal(GEP, TheCopy, - isOffset || !GEP->hasAllZeroIndices())) + isOffset || !GEP->hasAllZeroIndices(), + LifetimeMarkers)) return false; continue; } @@ -2554,6 +2566,16 @@ static bool isOnlyCopiedFromConstantGlobal(Value *V, MemTransferInst *&TheCopy, continue; } + // Lifetime intrinsics can be handled by the caller. + if (IntrinsicInst *II = dyn_cast(U)) { + if (II->getIntrinsicID() == Intrinsic::lifetime_start || + II->getIntrinsicID() == Intrinsic::lifetime_end) { + assert(II->use_empty() && "Lifetime markers have no result to use!"); + LifetimeMarkers.push_back(II); + continue; + } + } + // If this is isn't our memcpy/memmove, reject it as something we can't // handle. MemTransferInst *MI = dyn_cast(U); @@ -2590,9 +2612,11 @@ static bool isOnlyCopiedFromConstantGlobal(Value *V, MemTransferInst *&TheCopy, /// isOnlyCopiedFromConstantGlobal - Return true if the specified alloca is only /// modified by a copy from a constant global. If we can prove this, we can /// replace any uses of the alloca with uses of the global directly. -MemTransferInst *SROA::isOnlyCopiedFromConstantGlobal(AllocaInst *AI) { +MemTransferInst * +SROA::isOnlyCopiedFromConstantGlobal(AllocaInst *AI, + SmallVector &ToDelete) { MemTransferInst *TheCopy = 0; - if (::isOnlyCopiedFromConstantGlobal(AI, TheCopy, false)) + if (::isOnlyCopiedFromConstantGlobal(AI, TheCopy, false, ToDelete)) return TheCopy; return 0; } diff --git a/test/Transforms/ScalarRepl/memcpy-from-global.ll b/test/Transforms/ScalarRepl/memcpy-from-global.ll index 5b25864..59475ad 100644 --- a/test/Transforms/ScalarRepl/memcpy-from-global.ll +++ b/test/Transforms/ScalarRepl/memcpy-from-global.ll @@ -93,4 +93,18 @@ define void @test4() { ret void } +declare void @llvm.lifetime.start(i64, i8*) +define void @test5() { + %A = alloca %T + %a = bitcast %T* %A to i8* + call void @llvm.lifetime.start(i64 -1, i8* %a) + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %a, i8* bitcast (%T* @G to i8*), i64 124, i32 4, i1 false) + call void @baz(i8* byval %a) +; CHECK: @test5 +; CHECK-NEXT: %a = bitcast %T* @G to i8* +; CHECK-NEXT: call void @baz(i8* byval %a) + ret void +} + + declare void @baz(i8* byval) -- cgit v1.1 From f27229ee5ad121247b9c79e7605b19fccf781d8d Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Mon, 27 Jun 2011 15:00:36 +0000 Subject: Track live-out physical registers in MachineDCE. Patch by Sanjoy Das! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133910 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/DeadMachineInstructionElim.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/CodeGen/DeadMachineInstructionElim.cpp b/lib/CodeGen/DeadMachineInstructionElim.cpp index fdc1d91..6de6c0c 100644 --- a/lib/CodeGen/DeadMachineInstructionElim.cpp +++ b/lib/CodeGen/DeadMachineInstructionElim.cpp @@ -110,9 +110,14 @@ bool DeadMachineInstructionElim::runOnMachineFunction(MachineFunction &MF) { LivePhysRegs.set(Reg); } - // FIXME: Add live-ins from sucessors to LivePhysRegs. Normally, physregs - // are not live across blocks, but some targets (x86) can have flags live - // out of a block. + // Add live-ins from sucessors to LivePhysRegs. Normally, physregs are not + // live across blocks, but some targets (x86) can have flags live out of a + // block. + for (MachineBasicBlock::succ_iterator S = MBB->succ_begin(), + E = MBB->succ_end(); S != E; S++) + for (MachineBasicBlock::livein_iterator LI = (*S)->livein_begin(); + LI != (*S)->livein_end(); LI++) + LivePhysRegs.set(*LI); // Now scan the instructions and delete dead ones, tracking physreg // liveness as we go. -- cgit v1.1 From e8431ba8cb354f9a46d9fca55cc704361c7a8345 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Mon, 27 Jun 2011 17:27:37 +0000 Subject: Move all inline-asm-fpstack tests to a single file. Also fix some of the tests that were actually testing wrong behavior - An input operand in {st} is only popped by the inline asm when {st} is also in the clobber list. The original bug reports all had ~{st} clobbers as they should. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133916 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/CodeGen/X86/inline-asm-fpstack.ll | 80 +++++++++++++++++++++++++++++++-- test/CodeGen/X86/inline-asm-fpstack2.ll | 21 --------- test/CodeGen/X86/inline-asm-fpstack3.ll | 20 --------- test/CodeGen/X86/inline-asm-fpstack4.ll | 24 ---------- test/CodeGen/X86/inline-asm-fpstack5.ll | 15 ------- 5 files changed, 77 insertions(+), 83 deletions(-) delete mode 100644 test/CodeGen/X86/inline-asm-fpstack2.ll delete mode 100644 test/CodeGen/X86/inline-asm-fpstack3.ll delete mode 100644 test/CodeGen/X86/inline-asm-fpstack4.ll delete mode 100644 test/CodeGen/X86/inline-asm-fpstack5.ll diff --git a/test/CodeGen/X86/inline-asm-fpstack.ll b/test/CodeGen/X86/inline-asm-fpstack.ll index 6348fca..d15f7ff 100644 --- a/test/CodeGen/X86/inline-asm-fpstack.ll +++ b/test/CodeGen/X86/inline-asm-fpstack.ll @@ -26,7 +26,7 @@ define double @test2() { ; CHECK-NOT: fstp ; CHECK: ret define void @test3(x86_fp80 %X) { - call void asm sideeffect "frob ", "{st(0)},~{dirflag},~{fpsr},~{flags}"( x86_fp80 %X) + call void asm sideeffect "frob ", "{st(0)},~{st},~{dirflag},~{fpsr},~{flags}"( x86_fp80 %X) ret void } @@ -37,7 +37,7 @@ define void @test3(x86_fp80 %X) { ; CHECK-NOT: fstp ; CHECK: ret define void @test4(double %X) { - call void asm sideeffect "frob ", "{st(0)},~{dirflag},~{fpsr},~{flags}"( double %X) + call void asm sideeffect "frob ", "{st(0)},~{st},~{dirflag},~{fpsr},~{flags}"( double %X) ret void } @@ -49,7 +49,7 @@ define void @test4(double %X) { ; CHECK: ret define void @test5(double %X) { %Y = fadd double %X, 123.0 - call void asm sideeffect "frob ", "{st(0)},~{dirflag},~{fpsr},~{flags}"( double %Y) + call void asm sideeffect "frob ", "{st(0)},~{st},~{dirflag},~{fpsr},~{flags}"( double %Y) ret void } @@ -86,3 +86,77 @@ entry: ret void } +; PR4185 +; Passing a non-killed value to asm in {st}. +; Make sure it is duped before. +; asm kills st(0), so we shouldn't pop anything +; CHECK: testPR4185 +; CHECK: fld %st(0) +; CHECK: fistpl +; CHECK-NOT: fstp +; CHECK: fistpl +; CHECK-NOT: fstp +; CHECK: ret +; A valid alternative would be to remat the constant pool load before each +; inline asm. +define void @testPR4185() { +return: + call void asm sideeffect "fistpl $0", "{st},~{st}"(double 1.000000e+06) + call void asm sideeffect "fistpl $0", "{st},~{st}"(double 1.000000e+06) + ret void +} + +; PR4459 +; The return value from ceil must be duped before being consumed by asm. +; CHECK: testPR4459 +; CHECK: ceil +; CHECK: fld %st(0) +; CHECK-NOT: fxch +; CHECK: fistpl +; CHECK-NOT: fxch +; CHECK: fstpt +; CHECK: test +define void @testPR4459(x86_fp80 %a) { +entry: + %0 = call x86_fp80 @ceil(x86_fp80 %a) + call void asm sideeffect "fistpl $0", "{st},~{st}"( x86_fp80 %0) + call void @test3(x86_fp80 %0 ) + ret void +} +declare x86_fp80 @ceil(x86_fp80) + +; PR4484 +; test1 leaves a value on the stack that is needed after the asm. +; CHECK: testPR4484 +; CHECK: test1 +; CHECK-NOT: fstp +; Load %a from stack after ceil +; CHECK: fldt +; CHECK-NOT: fxch +; CHECK: fistpl +; CHECK-NOT: fstp +; Set up call to test. +; CHECK: fstpt +; CHECK: test +define void @testPR4484(x86_fp80 %a) { +entry: + %0 = call x86_fp80 @test1() + call void asm sideeffect "fistpl $0", "{st},~{st}"(x86_fp80 %a) + call void @test3(x86_fp80 %0) + ret void +} + +; PR4485 +; CHECK: testPR4485 +define void @testPR4485(x86_fp80* %a) { +entry: + %0 = load x86_fp80* %a, align 16 + %1 = fmul x86_fp80 %0, 0xK4006B400000000000000 + %2 = fmul x86_fp80 %1, 0xK4012F424000000000000 + tail call void asm sideeffect "fistpl $0", "{st},~{st}"(x86_fp80 %2) + %3 = load x86_fp80* %a, align 16 + %4 = fmul x86_fp80 %3, 0xK4006B400000000000000 + %5 = fmul x86_fp80 %4, 0xK4012F424000000000000 + tail call void asm sideeffect "fistpl $0", "{st},~{st}"(x86_fp80 %5) + ret void +} diff --git a/test/CodeGen/X86/inline-asm-fpstack2.ll b/test/CodeGen/X86/inline-asm-fpstack2.ll deleted file mode 100644 index 78037e0..0000000 --- a/test/CodeGen/X86/inline-asm-fpstack2.ll +++ /dev/null @@ -1,21 +0,0 @@ -; RUN: llc < %s -march=x86 | FileCheck %s -; PR4185 - -; Passing a non-killed value to asm in {st}. -; Make sure it is duped before. -; asm kills st(0), so we shouldn't pop anything -; CHECK: fld %st(0) -; CHECK: fistpl -; CHECK-NOT: fstp -; CHECK: fistpl -; CHECK-NOT: fstp -; CHECK: ret -define void @test() { -return: - call void asm sideeffect "fistpl $0", "{st}"(double 1.000000e+06) - call void asm sideeffect "fistpl $0", "{st}"(double 1.000000e+06) - ret void -} - -; A valid alternative would be to remat the constant pool load before each -; inline asm. diff --git a/test/CodeGen/X86/inline-asm-fpstack3.ll b/test/CodeGen/X86/inline-asm-fpstack3.ll deleted file mode 100644 index a609681..0000000 --- a/test/CodeGen/X86/inline-asm-fpstack3.ll +++ /dev/null @@ -1,20 +0,0 @@ -; RUN: llc < %s -march=x86 | FileCheck %s -; PR4459 - -; The return value from ceil must be duped before being consumed by asm. -; CHECK: ceil -; CHECK: fld %st(0) -; CHECK-NOT: fxch -; CHECK: fistpl -; CHECK-NOT: fxch -; CHECK: fstpt -; CHECK: test -define void @test2(x86_fp80 %a) { -entry: - %0 = call x86_fp80 @ceil(x86_fp80 %a) - call void asm sideeffect "fistpl $0", "{st}"( x86_fp80 %0) - call void @test(x86_fp80 %0 ) - ret void -} -declare x86_fp80 @ceil(x86_fp80) -declare void @test(x86_fp80) diff --git a/test/CodeGen/X86/inline-asm-fpstack4.ll b/test/CodeGen/X86/inline-asm-fpstack4.ll deleted file mode 100644 index ec572b4..0000000 --- a/test/CodeGen/X86/inline-asm-fpstack4.ll +++ /dev/null @@ -1,24 +0,0 @@ -; RUN: llc < %s -march=x86 | FileCheck %s -; PR4484 - -; ceil leaves a value on the stack that is needed after the asm. -; CHECK: ceil -; CHECK-NOT: fstp -; Load %a from stack after ceil -; CHECK: fldt -; CHECK-NOT: fxch -; CHECK: fistpl -; CHECK-NOT: fstp -; Set up call to test. -; CHECK: fstpt -; CHECK: test -define void @test2(x86_fp80 %a) { -entry: - %0 = call x86_fp80 @ceil() - call void asm sideeffect "fistpl $0", "{st},~{st}"(x86_fp80 %a) - call void @test(x86_fp80 %0) - ret void -} - -declare x86_fp80 @ceil() -declare void @test(x86_fp80) diff --git a/test/CodeGen/X86/inline-asm-fpstack5.ll b/test/CodeGen/X86/inline-asm-fpstack5.ll deleted file mode 100644 index 8b219cf..0000000 --- a/test/CodeGen/X86/inline-asm-fpstack5.ll +++ /dev/null @@ -1,15 +0,0 @@ -; RUN: llc < %s -march=x86 -; PR4485 - -define void @test(x86_fp80* %a) { -entry: - %0 = load x86_fp80* %a, align 16 - %1 = fmul x86_fp80 %0, 0xK4006B400000000000000 - %2 = fmul x86_fp80 %1, 0xK4012F424000000000000 - tail call void asm sideeffect "fistpl $0", "{st},~{st}"(x86_fp80 %2) - %3 = load x86_fp80* %a, align 16 - %4 = fmul x86_fp80 %3, 0xK4006B400000000000000 - %5 = fmul x86_fp80 %4, 0xK4012F424000000000000 - tail call void asm sideeffect "fistpl $0", "{st},~{st}"(x86_fp80 %5) - ret void -} -- cgit v1.1 From 4ef4c171dba8e479f5f3fe7acb22e9fe97a4d6f8 Mon Sep 17 00:00:00 2001 From: Andrew Trick Date: Mon, 27 Jun 2011 18:01:20 +0000 Subject: pre-RA-sched: Cleanup register pressure tracking. Removed the check that peeks past EXTRA_SUBREG, which I don't think makes sense any more. Intead treat it as a normal register def. No significant affect on x86 or ARM benchmarks. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133917 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp | 10 +++------- lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp | 10 +--------- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp index 1053b88..091f3bc 100644 --- a/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp +++ b/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp @@ -2029,13 +2029,9 @@ void RegReductionPQBase::UnscheduledNode(SUnit *SU) { unsigned POpc = PN->getMachineOpcode(); if (POpc == TargetOpcode::IMPLICIT_DEF) continue; - if (POpc == TargetOpcode::EXTRACT_SUBREG) { - EVT VT = PN->getOperand(0).getValueType(); - unsigned RCId = TLI->getRepRegClassFor(VT)->getID(); - RegPressure[RCId] += TLI->getRepRegClassCostFor(VT); - continue; - } else if (POpc == TargetOpcode::INSERT_SUBREG || - POpc == TargetOpcode::SUBREG_TO_REG) { + if (POpc == TargetOpcode::EXTRACT_SUBREG || + POpc == TargetOpcode::INSERT_SUBREG || + POpc == TargetOpcode::SUBREG_TO_REG) { EVT VT = PN->getValueType(0); unsigned RCId = TLI->getRepRegClassFor(VT)->getID(); RegPressure[RCId] += TLI->getRepRegClassCostFor(VT); diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp index f03bf10..edd9e46 100644 --- a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp +++ b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp @@ -520,15 +520,7 @@ void ScheduleDAGSDNodes::RegDefIter::Advance() { for (;DefIdx < NodeNumDefs; ++DefIdx) { if (!Node->hasAnyUseOfValue(DefIdx)) continue; - if (Node->isMachineOpcode() && - Node->getMachineOpcode() == TargetOpcode::EXTRACT_SUBREG && - Node->getOperand(0).getValueType() != MVT::untyped) { - // Propagate the incoming (full-register) type. I doubt it's needed. - ValueType = Node->getOperand(0).getValueType(); - } - else { - ValueType = Node->getValueType(DefIdx); - } + ValueType = Node->getValueType(DefIdx); ++DefIdx; return; // Found a normal regdef. } -- cgit v1.1 From 73f50d9bc3bd46cc0abeba9bb0d46977ba1aea42 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Mon, 27 Jun 2011 18:32:37 +0000 Subject: Merge XXXGenRegisterDesc.inc XXXGenRegisterNames.inc XXXGenRegisterInfo.h.inc into XXXGenRegisterInfo.inc. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133922 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMBaseInfo.h | 3 +- lib/Target/ARM/ARMBaseRegisterInfo.cpp | 4 +- lib/Target/ARM/ARMBaseRegisterInfo.h | 4 +- lib/Target/ARM/CMakeLists.txt | 3 - lib/Target/ARM/Makefile | 3 +- lib/Target/Alpha/Alpha.h | 4 +- lib/Target/Alpha/AlphaRegisterInfo.cpp | 5 +- lib/Target/Alpha/AlphaRegisterInfo.h | 4 +- lib/Target/Alpha/CMakeLists.txt | 3 - lib/Target/Alpha/Makefile | 3 +- lib/Target/Blackfin/Blackfin.h | 3 +- lib/Target/Blackfin/BlackfinRegisterInfo.cpp | 5 +- lib/Target/Blackfin/BlackfinRegisterInfo.h | 4 +- lib/Target/Blackfin/CMakeLists.txt | 3 - lib/Target/Blackfin/Makefile | 4 +- lib/Target/CellSPU/CMakeLists.txt | 3 - lib/Target/CellSPU/Makefile | 4 +- lib/Target/CellSPU/SPURegisterInfo.cpp | 4 +- lib/Target/CellSPU/SPURegisterInfo.h | 4 +- lib/Target/CellSPU/SPURegisterNames.h | 3 +- lib/Target/MBlaze/CMakeLists.txt | 3 - lib/Target/MBlaze/MBlaze.h | 3 +- lib/Target/MBlaze/MBlazeRegisterInfo.cpp | 5 +- lib/Target/MBlaze/MBlazeRegisterInfo.h | 4 +- lib/Target/MBlaze/Makefile | 4 +- lib/Target/MSP430/CMakeLists.txt | 3 - lib/Target/MSP430/MSP430.h | 3 +- lib/Target/MSP430/MSP430RegisterInfo.cpp | 4 +- lib/Target/MSP430/MSP430RegisterInfo.h | 4 +- lib/Target/MSP430/Makefile | 4 +- lib/Target/Mips/CMakeLists.txt | 3 - lib/Target/Mips/Makefile | 4 +- lib/Target/Mips/Mips.h | 3 +- lib/Target/Mips/MipsRegisterInfo.cpp | 4 +- lib/Target/Mips/MipsRegisterInfo.h | 4 +- lib/Target/PTX/CMakeLists.txt | 3 - lib/Target/PTX/Makefile | 3 - lib/Target/PTX/PTX.h | 3 +- lib/Target/PTX/PTXRegisterInfo.cpp | 6 +- lib/Target/PTX/PTXRegisterInfo.h | 3 +- lib/Target/PowerPC/CMakeLists.txt | 3 - lib/Target/PowerPC/Makefile | 4 +- lib/Target/PowerPC/PPC.h | 3 +- lib/Target/PowerPC/PPCRegisterInfo.cpp | 4 +- lib/Target/PowerPC/PPCRegisterInfo.h | 4 +- lib/Target/Sparc/CMakeLists.txt | 3 - lib/Target/Sparc/Makefile | 4 +- lib/Target/Sparc/Sparc.h | 3 +- lib/Target/Sparc/SparcRegisterInfo.cpp | 5 +- lib/Target/Sparc/SparcRegisterInfo.h | 4 +- lib/Target/SystemZ/CMakeLists.txt | 3 - lib/Target/SystemZ/Makefile | 4 +- lib/Target/SystemZ/SystemZ.h | 3 +- lib/Target/SystemZ/SystemZRegisterInfo.cpp | 5 +- lib/Target/SystemZ/SystemZRegisterInfo.h | 4 +- lib/Target/X86/CMakeLists.txt | 3 - lib/Target/X86/Disassembler/X86Disassembler.cpp | 3 +- lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp | 5 +- lib/Target/X86/MCTargetDesc/X86TargetDesc.cpp | 4 +- lib/Target/X86/MCTargetDesc/X86TargetDesc.h | 3 +- lib/Target/X86/Makefile | 3 +- lib/Target/X86/X86RegisterInfo.cpp | 5 +- lib/Target/X86/X86RegisterInfo.h | 4 +- lib/Target/XCore/CMakeLists.txt | 3 - lib/Target/XCore/Makefile | 4 +- lib/Target/XCore/XCore.h | 3 +- lib/Target/XCore/XCoreRegisterInfo.cpp | 5 +- lib/Target/XCore/XCoreRegisterInfo.h | 4 +- utils/TableGen/RegisterInfoEmitter.cpp | 261 +++++++++++++---------- utils/TableGen/RegisterInfoEmitter.h | 20 +- utils/TableGen/TableGen.cpp | 19 +- 71 files changed, 295 insertions(+), 256 deletions(-) diff --git a/lib/Target/ARM/ARMBaseInfo.h b/lib/Target/ARM/ARMBaseInfo.h index 36edbad..91e9fd1 100644 --- a/lib/Target/ARM/ARMBaseInfo.h +++ b/lib/Target/ARM/ARMBaseInfo.h @@ -25,7 +25,8 @@ // Defines symbolic names for ARM registers. This defines a mapping from // register name to register number. // -#include "ARMGenRegisterNames.inc" +#define GET_REGINFO_ENUM +#include "ARMGenRegisterInfo.inc" // Defines symbolic names for the ARM instructions. // diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/lib/Target/ARM/ARMBaseRegisterInfo.cpp index 0e74ac0..92c98da 100644 --- a/lib/Target/ARM/ARMBaseRegisterInfo.cpp +++ b/lib/Target/ARM/ARMBaseRegisterInfo.cpp @@ -39,7 +39,9 @@ #include "llvm/ADT/BitVector.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/CommandLine.h" -#include "ARMGenRegisterDesc.inc" + +#define GET_REGINFO_MC_DESC +#define GET_REGINFO_TARGET_DESC #include "ARMGenRegisterInfo.inc" using namespace llvm; diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.h b/lib/Target/ARM/ARMBaseRegisterInfo.h index 70b6f01..b4b4059 100644 --- a/lib/Target/ARM/ARMBaseRegisterInfo.h +++ b/lib/Target/ARM/ARMBaseRegisterInfo.h @@ -16,7 +16,9 @@ #include "ARM.h" #include "llvm/Target/TargetRegisterInfo.h" -#include "ARMGenRegisterInfo.h.inc" + +#define GET_REGINFO_HEADER +#include "ARMGenRegisterInfo.inc" namespace llvm { class ARMSubtarget; diff --git a/lib/Target/ARM/CMakeLists.txt b/lib/Target/ARM/CMakeLists.txt index 6cb9689..0a0ed3c 100644 --- a/lib/Target/ARM/CMakeLists.txt +++ b/lib/Target/ARM/CMakeLists.txt @@ -1,8 +1,5 @@ set(LLVM_TARGET_DEFINITIONS ARM.td) -tablegen(ARMGenRegisterNames.inc -gen-register-enums) -tablegen(ARMGenRegisterDesc.inc -gen-register-desc) -tablegen(ARMGenRegisterInfo.h.inc -gen-register-info-header) tablegen(ARMGenRegisterInfo.inc -gen-register-info) tablegen(ARMGenInstrNames.inc -gen-instr-enums) tablegen(ARMGenInstrInfo.inc -gen-instr-desc) diff --git a/lib/Target/ARM/Makefile b/lib/Target/ARM/Makefile index 0a42514..9ecbd6b 100644 --- a/lib/Target/ARM/Makefile +++ b/lib/Target/ARM/Makefile @@ -12,8 +12,7 @@ LIBRARYNAME = LLVMARMCodeGen TARGET = ARM # Make sure that tblgen is run, first thing. -BUILT_SOURCES = ARMGenRegisterNames.inc ARMGenRegisterDesc.inc \ - ARMGenRegisterInfo.h.inc ARMGenRegisterInfo.inc \ +BUILT_SOURCES = ARMGenRegisterInfo.inc \ ARMGenInstrNames.inc ARMGenInstrInfo.inc \ ARMGenAsmWriter.inc ARMGenAsmMatcher.inc \ ARMGenDAGISel.inc ARMGenSubtarget.inc \ diff --git a/lib/Target/Alpha/Alpha.h b/lib/Target/Alpha/Alpha.h index 2c359da..174d261 100644 --- a/lib/Target/Alpha/Alpha.h +++ b/lib/Target/Alpha/Alpha.h @@ -44,7 +44,9 @@ namespace llvm { // Defines symbolic names for Alpha registers. This defines a mapping from // register name to register number. // -#include "AlphaGenRegisterNames.inc" + +#define GET_REGINFO_ENUM +#include "AlphaGenRegisterInfo.inc" // Defines symbolic names for the Alpha instructions. // diff --git a/lib/Target/Alpha/AlphaRegisterInfo.cpp b/lib/Target/Alpha/AlphaRegisterInfo.cpp index 5ff846e..3eef05f 100644 --- a/lib/Target/Alpha/AlphaRegisterInfo.cpp +++ b/lib/Target/Alpha/AlphaRegisterInfo.cpp @@ -33,8 +33,11 @@ #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" #include -#include "AlphaGenRegisterDesc.inc" + +#define GET_REGINFO_MC_DESC +#define GET_REGINFO_TARGET_DESC #include "AlphaGenRegisterInfo.inc" + using namespace llvm; AlphaRegisterInfo::AlphaRegisterInfo(const TargetInstrInfo &tii) diff --git a/lib/Target/Alpha/AlphaRegisterInfo.h b/lib/Target/Alpha/AlphaRegisterInfo.h index ffe6cf1..1072bf7 100644 --- a/lib/Target/Alpha/AlphaRegisterInfo.h +++ b/lib/Target/Alpha/AlphaRegisterInfo.h @@ -15,7 +15,9 @@ #define ALPHAREGISTERINFO_H #include "llvm/Target/TargetRegisterInfo.h" -#include "AlphaGenRegisterInfo.h.inc" + +#define GET_REGINFO_HEADER +#include "AlphaGenRegisterInfo.inc" namespace llvm { diff --git a/lib/Target/Alpha/CMakeLists.txt b/lib/Target/Alpha/CMakeLists.txt index 1834b06..bcde447 100644 --- a/lib/Target/Alpha/CMakeLists.txt +++ b/lib/Target/Alpha/CMakeLists.txt @@ -1,8 +1,5 @@ set(LLVM_TARGET_DEFINITIONS Alpha.td) -tablegen(AlphaGenRegisterNames.inc -gen-register-enums) -tablegen(AlphaGenRegisterDesc.inc -gen-register-desc) -tablegen(AlphaGenRegisterInfo.h.inc -gen-register-info-header) tablegen(AlphaGenRegisterInfo.inc -gen-register-info) tablegen(AlphaGenInstrNames.inc -gen-instr-enums) tablegen(AlphaGenInstrInfo.inc -gen-instr-desc) diff --git a/lib/Target/Alpha/Makefile b/lib/Target/Alpha/Makefile index f029793..bd280a0 100644 --- a/lib/Target/Alpha/Makefile +++ b/lib/Target/Alpha/Makefile @@ -12,8 +12,7 @@ LIBRARYNAME = LLVMAlphaCodeGen TARGET = Alpha # Make sure that tblgen is run, first thing. -BUILT_SOURCES = AlphaGenRegisterNames.inc AlphaGenRegisterDesc.inc \ - AlphaGenRegisterInfo.h.inc AlphaGenRegisterInfo.inc \ +BUILT_SOURCES = AlphaGenRegisterInfo.inc \ AlphaGenInstrNames.inc AlphaGenInstrInfo.inc \ AlphaGenAsmWriter.inc AlphaGenDAGISel.inc \ AlphaGenCallingConv.inc AlphaGenSubtarget.inc diff --git a/lib/Target/Blackfin/Blackfin.h b/lib/Target/Blackfin/Blackfin.h index ec1fa86..3285c4f 100644 --- a/lib/Target/Blackfin/Blackfin.h +++ b/lib/Target/Blackfin/Blackfin.h @@ -30,7 +30,8 @@ namespace llvm { // Defines symbolic names for Blackfin registers. This defines a mapping from // register name to register number. -#include "BlackfinGenRegisterNames.inc" +#define GET_REGINFO_ENUM +#include "BlackfinGenRegisterInfo.inc" // Defines symbolic names for the Blackfin instructions. #include "BlackfinGenInstrNames.inc" diff --git a/lib/Target/Blackfin/BlackfinRegisterInfo.cpp b/lib/Target/Blackfin/BlackfinRegisterInfo.cpp index 6377d8e..aa43744 100644 --- a/lib/Target/Blackfin/BlackfinRegisterInfo.cpp +++ b/lib/Target/Blackfin/BlackfinRegisterInfo.cpp @@ -29,8 +29,11 @@ #include "llvm/Type.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" -#include "BlackfinGenRegisterDesc.inc" + +#define GET_REGINFO_MC_DESC +#define GET_REGINFO_TARGET_DESC #include "BlackfinGenRegisterInfo.inc" + using namespace llvm; BlackfinRegisterInfo::BlackfinRegisterInfo(BlackfinSubtarget &st, diff --git a/lib/Target/Blackfin/BlackfinRegisterInfo.h b/lib/Target/Blackfin/BlackfinRegisterInfo.h index 375d277..86f45c1 100644 --- a/lib/Target/Blackfin/BlackfinRegisterInfo.h +++ b/lib/Target/Blackfin/BlackfinRegisterInfo.h @@ -16,7 +16,9 @@ #define BLACKFINREGISTERINFO_H #include "llvm/Target/TargetRegisterInfo.h" -#include "BlackfinGenRegisterInfo.h.inc" + +#define GET_REGINFO_HEADER +#include "BlackfinGenRegisterInfo.inc" namespace llvm { diff --git a/lib/Target/Blackfin/CMakeLists.txt b/lib/Target/Blackfin/CMakeLists.txt index 10896c5..c59b5a3 100644 --- a/lib/Target/Blackfin/CMakeLists.txt +++ b/lib/Target/Blackfin/CMakeLists.txt @@ -1,8 +1,5 @@ set(LLVM_TARGET_DEFINITIONS Blackfin.td) -tablegen(BlackfinGenRegisterNames.inc -gen-register-enums) -tablegen(BlackfinGenRegisterDesc.inc -gen-register-desc) -tablegen(BlackfinGenRegisterInfo.h.inc -gen-register-info-header) tablegen(BlackfinGenRegisterInfo.inc -gen-register-info) tablegen(BlackfinGenInstrNames.inc -gen-instr-enums) tablegen(BlackfinGenInstrInfo.inc -gen-instr-desc) diff --git a/lib/Target/Blackfin/Makefile b/lib/Target/Blackfin/Makefile index 8ea1dfb..c05d27b 100644 --- a/lib/Target/Blackfin/Makefile +++ b/lib/Target/Blackfin/Makefile @@ -12,9 +12,7 @@ LIBRARYNAME = LLVMBlackfinCodeGen TARGET = Blackfin # Make sure that tblgen is run, first thing. -BUILT_SOURCES = BlackfinGenRegisterNames.inc BlackfinGenRegisterDesc.inc \ - BlackfinGenRegisterInfo.h.inc BlackfinGenRegisterInfo.inc \ - BlackfinGenInstrNames.inc \ +BUILT_SOURCES = BlackfinGenRegisterInfo.inc BlackfinGenInstrNames.inc \ BlackfinGenInstrInfo.inc BlackfinGenAsmWriter.inc \ BlackfinGenDAGISel.inc BlackfinGenSubtarget.inc \ BlackfinGenCallingConv.inc BlackfinGenIntrinsics.inc diff --git a/lib/Target/CellSPU/CMakeLists.txt b/lib/Target/CellSPU/CMakeLists.txt index dc1f708..1cce2c1 100644 --- a/lib/Target/CellSPU/CMakeLists.txt +++ b/lib/Target/CellSPU/CMakeLists.txt @@ -1,11 +1,8 @@ set(LLVM_TARGET_DEFINITIONS SPU.td) tablegen(SPUGenInstrNames.inc -gen-instr-enums) -tablegen(SPUGenRegisterNames.inc -gen-register-enums) tablegen(SPUGenAsmWriter.inc -gen-asm-writer) tablegen(SPUGenCodeEmitter.inc -gen-emitter) -tablegen(SPUGenRegisterDesc.inc -gen-register-desc) -tablegen(SPUGenRegisterInfo.h.inc -gen-register-info-header) tablegen(SPUGenRegisterInfo.inc -gen-register-info) tablegen(SPUGenInstrInfo.inc -gen-instr-desc) tablegen(SPUGenDAGISel.inc -gen-dag-isel) diff --git a/lib/Target/CellSPU/Makefile b/lib/Target/CellSPU/Makefile index de8a947..270bd6b 100644 --- a/lib/Target/CellSPU/Makefile +++ b/lib/Target/CellSPU/Makefile @@ -10,10 +10,8 @@ LEVEL = ../../.. LIBRARYNAME = LLVMCellSPUCodeGen TARGET = SPU -BUILT_SOURCES = SPUGenInstrNames.inc \ +BUILT_SOURCES = SPUGenInstrNames.inc SPUGenRegisterInfo.inc \ SPUGenAsmWriter.inc SPUGenCodeEmitter.inc \ - SPUGenRegisterNames.inc SPUGenRegisterDesc.inc \ - SPUGenRegisterInfo.h.inc SPUGenRegisterInfo.inc \ SPUGenInstrInfo.inc SPUGenDAGISel.inc \ SPUGenSubtarget.inc SPUGenCallingConv.inc diff --git a/lib/Target/CellSPU/SPURegisterInfo.cpp b/lib/Target/CellSPU/SPURegisterInfo.cpp index 34f3f9b..a84dd5a 100644 --- a/lib/Target/CellSPU/SPURegisterInfo.cpp +++ b/lib/Target/CellSPU/SPURegisterInfo.cpp @@ -42,7 +42,9 @@ #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" #include -#include "SPUGenRegisterDesc.inc" + +#define GET_REGINFO_MC_DESC +#define GET_REGINFO_TARGET_DESC #include "SPUGenRegisterInfo.inc" using namespace llvm; diff --git a/lib/Target/CellSPU/SPURegisterInfo.h b/lib/Target/CellSPU/SPURegisterInfo.h index 6ecf0f2..5e014f8 100644 --- a/lib/Target/CellSPU/SPURegisterInfo.h +++ b/lib/Target/CellSPU/SPURegisterInfo.h @@ -16,7 +16,9 @@ #define SPU_REGISTERINFO_H #include "SPU.h" -#include "SPUGenRegisterInfo.h.inc" + +#define GET_REGINFO_HEADER +#include "SPUGenRegisterInfo.inc" namespace llvm { class SPUSubtarget; diff --git a/lib/Target/CellSPU/SPURegisterNames.h b/lib/Target/CellSPU/SPURegisterNames.h index 6c3afdf..e557ed3 100644 --- a/lib/Target/CellSPU/SPURegisterNames.h +++ b/lib/Target/CellSPU/SPURegisterNames.h @@ -13,6 +13,7 @@ // Define symbolic names for Cell registers. This defines a mapping from // register name to register number. // -#include "SPUGenRegisterNames.inc" +#define GET_REGINFO_ENUM +#include "SPUGenRegisterInfo.inc" #endif diff --git a/lib/Target/MBlaze/CMakeLists.txt b/lib/Target/MBlaze/CMakeLists.txt index 009564e..86d030d 100644 --- a/lib/Target/MBlaze/CMakeLists.txt +++ b/lib/Target/MBlaze/CMakeLists.txt @@ -1,9 +1,6 @@ set(LLVM_TARGET_DEFINITIONS MBlaze.td) -tablegen(MBlazeGenRegisterNames.inc -gen-register-enums) -tablegen(MBlazeGenRegisterDesc.inc -gen-register-desc) tablegen(MBlazeGenRegisterInfo.h.inc -gen-register-info-header) -tablegen(MBlazeGenRegisterInfo.inc -gen-register-info) tablegen(MBlazeGenInstrNames.inc -gen-instr-enums) tablegen(MBlazeGenInstrInfo.inc -gen-instr-desc) tablegen(MBlazeGenCodeEmitter.inc -gen-emitter) diff --git a/lib/Target/MBlaze/MBlaze.h b/lib/Target/MBlaze/MBlaze.h index 00c73f0..c6181f7 100644 --- a/lib/Target/MBlaze/MBlaze.h +++ b/lib/Target/MBlaze/MBlaze.h @@ -39,7 +39,8 @@ namespace llvm { // Defines symbolic names for MBlaze registers. This defines a mapping from // register name to register number. -#include "MBlazeGenRegisterNames.inc" +#define GET_REGINFO_ENUM +#include "MBlazeGenRegisterInfo.inc" // Defines symbolic names for the MBlaze instructions. #include "MBlazeGenInstrNames.inc" diff --git a/lib/Target/MBlaze/MBlazeRegisterInfo.cpp b/lib/Target/MBlaze/MBlazeRegisterInfo.cpp index f52c2e1..415c83b 100644 --- a/lib/Target/MBlaze/MBlazeRegisterInfo.cpp +++ b/lib/Target/MBlaze/MBlazeRegisterInfo.cpp @@ -36,8 +36,11 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" -#include "MBlazeGenRegisterDesc.inc" + +#define GET_REGINFO_MC_DESC +#define GET_REGINFO_TARGET_DESC #include "MBlazeGenRegisterInfo.inc" + using namespace llvm; MBlazeRegisterInfo:: diff --git a/lib/Target/MBlaze/MBlazeRegisterInfo.h b/lib/Target/MBlaze/MBlazeRegisterInfo.h index 3807839..7ebce21 100644 --- a/lib/Target/MBlaze/MBlazeRegisterInfo.h +++ b/lib/Target/MBlaze/MBlazeRegisterInfo.h @@ -17,7 +17,9 @@ #include "MBlaze.h" #include "llvm/Target/TargetRegisterInfo.h" -#include "MBlazeGenRegisterInfo.h.inc" + +#define GET_REGINFO_HEADER +#include "MBlazeGenRegisterInfo.inc" namespace llvm { class MBlazeSubtarget; diff --git a/lib/Target/MBlaze/Makefile b/lib/Target/MBlaze/Makefile index 81fd5f7..010885f 100644 --- a/lib/Target/MBlaze/Makefile +++ b/lib/Target/MBlaze/Makefile @@ -11,9 +11,7 @@ LIBRARYNAME = LLVMMBlazeCodeGen TARGET = MBlaze # Make sure that tblgen is run, first thing. -BUILT_SOURCES = MBlazeGenRegisterInfo.h.inc MBlazeGenRegisterNames.inc \ - MBlazeGenRegisterInfo.inc MBlazeGenRegisterDesc.inc \ - MBlazeGenInstrNames.inc \ +BUILT_SOURCES = MBlazeGenRegisterInfo.inc MBlazeGenInstrNames.inc \ MBlazeGenInstrInfo.inc MBlazeGenAsmWriter.inc \ MBlazeGenDAGISel.inc MBlazeGenAsmMatcher.inc \ MBlazeGenCodeEmitter.inc MBlazeGenCallingConv.inc \ diff --git a/lib/Target/MSP430/CMakeLists.txt b/lib/Target/MSP430/CMakeLists.txt index 90752fa..bf58fd2 100644 --- a/lib/Target/MSP430/CMakeLists.txt +++ b/lib/Target/MSP430/CMakeLists.txt @@ -1,8 +1,5 @@ set(LLVM_TARGET_DEFINITIONS MSP430.td) -tablegen(MSP430GenRegisterNames.inc -gen-register-enums) -tablegen(MSP430GenRegisterDesc.inc -gen-register-desc) -tablegen(MSP430GenRegisterInfo.h.inc -gen-register-info-header) tablegen(MSP430GenRegisterInfo.inc -gen-register-info) tablegen(MSP430GenInstrNames.inc -gen-instr-enums) tablegen(MSP430GenInstrInfo.inc -gen-instr-desc) diff --git a/lib/Target/MSP430/MSP430.h b/lib/Target/MSP430/MSP430.h index e742118..2dabe7c 100644 --- a/lib/Target/MSP430/MSP430.h +++ b/lib/Target/MSP430/MSP430.h @@ -47,7 +47,8 @@ namespace llvm { // Defines symbolic names for MSP430 registers. // This defines a mapping from register name to register number. -#include "MSP430GenRegisterNames.inc" +#define GET_REGINFO_ENUM +#include "MSP430GenRegisterInfo.inc" // Defines symbolic names for the MSP430 instructions. #include "MSP430GenInstrNames.inc" diff --git a/lib/Target/MSP430/MSP430RegisterInfo.cpp b/lib/Target/MSP430/MSP430RegisterInfo.cpp index 397b7b4..0a2e93a 100644 --- a/lib/Target/MSP430/MSP430RegisterInfo.cpp +++ b/lib/Target/MSP430/MSP430RegisterInfo.cpp @@ -25,7 +25,9 @@ #include "llvm/Target/TargetOptions.h" #include "llvm/ADT/BitVector.h" #include "llvm/Support/ErrorHandling.h" -#include "MSP430GenRegisterDesc.inc" + +#define GET_REGINFO_MC_DESC +#define GET_REGINFO_TARGET_DESC #include "MSP430GenRegisterInfo.inc" using namespace llvm; diff --git a/lib/Target/MSP430/MSP430RegisterInfo.h b/lib/Target/MSP430/MSP430RegisterInfo.h index e820558..fb70594 100644 --- a/lib/Target/MSP430/MSP430RegisterInfo.h +++ b/lib/Target/MSP430/MSP430RegisterInfo.h @@ -15,7 +15,9 @@ #define LLVM_TARGET_MSP430REGISTERINFO_H #include "llvm/Target/TargetRegisterInfo.h" -#include "MSP430GenRegisterInfo.h.inc" + +#define GET_REGINFO_HEADER +#include "MSP430GenRegisterInfo.inc" namespace llvm { diff --git a/lib/Target/MSP430/Makefile b/lib/Target/MSP430/Makefile index 8635646..cdbbf0e 100644 --- a/lib/Target/MSP430/Makefile +++ b/lib/Target/MSP430/Makefile @@ -12,9 +12,7 @@ LIBRARYNAME = LLVMMSP430CodeGen TARGET = MSP430 # Make sure that tblgen is run, first thing. -BUILT_SOURCES = MSP430GenRegisterInfo.h.inc MSP430GenRegisterNames.inc \ - MSP430GenRegisterInfo.inc MSP430GenRegisterDesc.inc \ - MSP430GenInstrNames.inc \ +BUILT_SOURCES = MSP430GenRegisterInfo.inc MSP430GenInstrNames.inc \ MSP430GenInstrInfo.inc MSP430GenAsmWriter.inc \ MSP430GenDAGISel.inc MSP430GenCallingConv.inc \ MSP430GenSubtarget.inc diff --git a/lib/Target/Mips/CMakeLists.txt b/lib/Target/Mips/CMakeLists.txt index f9d9536..aa51fbf 100644 --- a/lib/Target/Mips/CMakeLists.txt +++ b/lib/Target/Mips/CMakeLists.txt @@ -1,8 +1,5 @@ set(LLVM_TARGET_DEFINITIONS Mips.td) -tablegen(MipsGenRegisterNames.inc -gen-register-enums) -tablegen(MipsGenRegisterDesc.inc -gen-register-desc) -tablegen(MipsGenRegisterInfo.h.inc -gen-register-info-header) tablegen(MipsGenRegisterInfo.inc -gen-register-info) tablegen(MipsGenInstrNames.inc -gen-instr-enums) tablegen(MipsGenInstrInfo.inc -gen-instr-desc) diff --git a/lib/Target/Mips/Makefile b/lib/Target/Mips/Makefile index d7eab61..3f5cfd7 100644 --- a/lib/Target/Mips/Makefile +++ b/lib/Target/Mips/Makefile @@ -12,9 +12,7 @@ LIBRARYNAME = LLVMMipsCodeGen TARGET = Mips # Make sure that tblgen is run, first thing. -BUILT_SOURCES = MipsGenRegisterInfo.h.inc MipsGenRegisterNames.inc \ - MipsGenRegisterInfo.inc MipsGenRegisterDesc.inc \ - MipsGenInstrNames.inc \ +BUILT_SOURCES = MipsGenRegisterInfo.inc MipsGenInstrNames.inc \ MipsGenInstrInfo.inc MipsGenAsmWriter.inc \ MipsGenDAGISel.inc MipsGenCallingConv.inc \ MipsGenSubtarget.inc diff --git a/lib/Target/Mips/Mips.h b/lib/Target/Mips/Mips.h index 76a26a9..d296b36 100644 --- a/lib/Target/Mips/Mips.h +++ b/lib/Target/Mips/Mips.h @@ -35,7 +35,8 @@ namespace llvm { // Defines symbolic names for Mips registers. This defines a mapping from // register name to register number. -#include "MipsGenRegisterNames.inc" +#define GET_REGINFO_ENUM +#include "MipsGenRegisterInfo.inc" // Defines symbolic names for the Mips instructions. #include "MipsGenInstrNames.inc" diff --git a/lib/Target/Mips/MipsRegisterInfo.cpp b/lib/Target/Mips/MipsRegisterInfo.cpp index 6fdcf45..2b74f73 100644 --- a/lib/Target/Mips/MipsRegisterInfo.cpp +++ b/lib/Target/Mips/MipsRegisterInfo.cpp @@ -35,7 +35,9 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" -#include "MipsGenRegisterDesc.inc" + +#define GET_REGINFO_MC_DESC +#define GET_REGINFO_TARGET_DESC #include "MipsGenRegisterInfo.inc" using namespace llvm; diff --git a/lib/Target/Mips/MipsRegisterInfo.h b/lib/Target/Mips/MipsRegisterInfo.h index 76b0035..646369b 100644 --- a/lib/Target/Mips/MipsRegisterInfo.h +++ b/lib/Target/Mips/MipsRegisterInfo.h @@ -16,7 +16,9 @@ #include "Mips.h" #include "llvm/Target/TargetRegisterInfo.h" -#include "MipsGenRegisterInfo.h.inc" + +#define GET_REGINFO_HEADER +#include "MipsGenRegisterInfo.inc" namespace llvm { class MipsSubtarget; diff --git a/lib/Target/PTX/CMakeLists.txt b/lib/Target/PTX/CMakeLists.txt index 540af72..42b1925 100644 --- a/lib/Target/PTX/CMakeLists.txt +++ b/lib/Target/PTX/CMakeLists.txt @@ -5,10 +5,7 @@ tablegen(PTXGenCallingConv.inc -gen-callingconv) tablegen(PTXGenDAGISel.inc -gen-dag-isel) tablegen(PTXGenInstrInfo.inc -gen-instr-desc) tablegen(PTXGenInstrNames.inc -gen-instr-enums) -tablegen(PTXGenRegisterDesc.inc -gen-register-desc) tablegen(PTXGenRegisterInfo.inc -gen-register-info) -tablegen(PTXGenRegisterInfo.h.inc -gen-register-info-header) -tablegen(PTXGenRegisterNames.inc -gen-register-enums) tablegen(PTXGenSubtarget.inc -gen-subtarget) add_llvm_target(PTXCodeGen diff --git a/lib/Target/PTX/Makefile b/lib/Target/PTX/Makefile index 1e471de..7c3f318 100644 --- a/lib/Target/PTX/Makefile +++ b/lib/Target/PTX/Makefile @@ -17,10 +17,7 @@ BUILT_SOURCES = PTXGenAsmWriter.inc \ PTXGenDAGISel.inc \ PTXGenInstrInfo.inc \ PTXGenInstrNames.inc \ - PTXGenRegisterDesc.inc \ PTXGenRegisterInfo.inc \ - PTXGenRegisterInfo.h.inc \ - PTXGenRegisterNames.inc \ PTXGenSubtarget.inc DIRS = TargetInfo diff --git a/lib/Target/PTX/PTX.h b/lib/Target/PTX/PTX.h index ec2be92..345f87a 100644 --- a/lib/Target/PTX/PTX.h +++ b/lib/Target/PTX/PTX.h @@ -47,7 +47,8 @@ namespace llvm { } // namespace llvm; // Defines symbolic names for PTX registers. -#include "PTXGenRegisterNames.inc" +#define GET_REGINFO_ENUM +#include "PTXGenRegisterInfo.inc" // Defines symbolic names for the PTX instructions. #include "PTXGenInstrNames.inc" diff --git a/lib/Target/PTX/PTXRegisterInfo.cpp b/lib/Target/PTX/PTXRegisterInfo.cpp index 5673f96..06c5424 100644 --- a/lib/Target/PTX/PTXRegisterInfo.cpp +++ b/lib/Target/PTX/PTXRegisterInfo.cpp @@ -17,11 +17,11 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" -using namespace llvm; - -#include "PTXGenRegisterDesc.inc" +#define GET_REGINFO_MC_DESC +#define GET_REGINFO_TARGET_DESC #include "PTXGenRegisterInfo.inc" +using namespace llvm; PTXRegisterInfo::PTXRegisterInfo(PTXTargetMachine &TM, const TargetInstrInfo &TII) diff --git a/lib/Target/PTX/PTXRegisterInfo.h b/lib/Target/PTX/PTXRegisterInfo.h index 67e8a1b..0b63cb6 100644 --- a/lib/Target/PTX/PTXRegisterInfo.h +++ b/lib/Target/PTX/PTXRegisterInfo.h @@ -17,7 +17,8 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/ADT/BitVector.h" -#include "PTXGenRegisterInfo.h.inc" +#define GET_REGINFO_HEADER +#include "PTXGenRegisterInfo.inc" namespace llvm { class PTXTargetMachine; diff --git a/lib/Target/PowerPC/CMakeLists.txt b/lib/Target/PowerPC/CMakeLists.txt index 99caa99..ca5daec 100644 --- a/lib/Target/PowerPC/CMakeLists.txt +++ b/lib/Target/PowerPC/CMakeLists.txt @@ -1,12 +1,9 @@ set(LLVM_TARGET_DEFINITIONS PPC.td) tablegen(PPCGenInstrNames.inc -gen-instr-enums) -tablegen(PPCGenRegisterNames.inc -gen-register-enums) tablegen(PPCGenAsmWriter.inc -gen-asm-writer) tablegen(PPCGenCodeEmitter.inc -gen-emitter) tablegen(PPCGenMCCodeEmitter.inc -gen-emitter -mc-emitter) -tablegen(PPCGenRegisterDesc.inc -gen-register-desc) -tablegen(PPCGenRegisterInfo.h.inc -gen-register-info-header) tablegen(PPCGenRegisterInfo.inc -gen-register-info) tablegen(PPCGenInstrInfo.inc -gen-instr-desc) tablegen(PPCGenDAGISel.inc -gen-dag-isel) diff --git a/lib/Target/PowerPC/Makefile b/lib/Target/PowerPC/Makefile index 3d01792..d7a57f9 100644 --- a/lib/Target/PowerPC/Makefile +++ b/lib/Target/PowerPC/Makefile @@ -12,10 +12,8 @@ LIBRARYNAME = LLVMPowerPCCodeGen TARGET = PPC # Make sure that tblgen is run, first thing. -BUILT_SOURCES = PPCGenInstrNames.inc PPCGenRegisterNames.inc \ +BUILT_SOURCES = PPCGenInstrNames.inc PPCGenRegisterInfo.inc \ PPCGenAsmWriter.inc PPCGenCodeEmitter.inc \ - PPCGenRegisterDesc.inc \ - PPCGenRegisterInfo.h.inc PPCGenRegisterInfo.inc \ PPCGenInstrInfo.inc PPCGenDAGISel.inc \ PPCGenSubtarget.inc PPCGenCallingConv.inc \ PPCGenMCCodeEmitter.inc diff --git a/lib/Target/PowerPC/PPC.h b/lib/Target/PowerPC/PPC.h index 92672b5..a8ab8f2 100644 --- a/lib/Target/PowerPC/PPC.h +++ b/lib/Target/PowerPC/PPC.h @@ -84,7 +84,8 @@ namespace llvm { // Defines symbolic names for PowerPC registers. This defines a mapping from // register name to register number. // -#include "PPCGenRegisterNames.inc" +#define GET_REGINFO_ENUM +#include "PPCGenRegisterInfo.inc" // Defines symbolic names for the PowerPC instructions. // diff --git a/lib/Target/PowerPC/PPCRegisterInfo.cpp b/lib/Target/PowerPC/PPCRegisterInfo.cpp index 3950517..bd5c722 100644 --- a/lib/Target/PowerPC/PPCRegisterInfo.cpp +++ b/lib/Target/PowerPC/PPCRegisterInfo.cpp @@ -43,7 +43,9 @@ #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" #include -#include "PPCGenRegisterDesc.inc" + +#define GET_REGINFO_MC_DESC +#define GET_REGINFO_TARGET_DESC #include "PPCGenRegisterInfo.inc" // FIXME (64-bit): Eventually enable by default. diff --git a/lib/Target/PowerPC/PPCRegisterInfo.h b/lib/Target/PowerPC/PPCRegisterInfo.h index 48c2562..33fe5eb 100644 --- a/lib/Target/PowerPC/PPCRegisterInfo.h +++ b/lib/Target/PowerPC/PPCRegisterInfo.h @@ -16,9 +16,11 @@ #define POWERPC32_REGISTERINFO_H #include "PPC.h" -#include "PPCGenRegisterInfo.h.inc" #include +#define GET_REGINFO_HEADER +#include "PPCGenRegisterInfo.inc" + namespace llvm { class PPCSubtarget; class TargetInstrInfo; diff --git a/lib/Target/Sparc/CMakeLists.txt b/lib/Target/Sparc/CMakeLists.txt index 243e889..1a5b036 100644 --- a/lib/Target/Sparc/CMakeLists.txt +++ b/lib/Target/Sparc/CMakeLists.txt @@ -1,8 +1,5 @@ set(LLVM_TARGET_DEFINITIONS Sparc.td) -tablegen(SparcGenRegisterNames.inc -gen-register-enums) -tablegen(SparcGenRegisterDesc.inc -gen-register-desc) -tablegen(SparcGenRegisterInfo.h.inc -gen-register-info-header) tablegen(SparcGenRegisterInfo.inc -gen-register-info) tablegen(SparcGenInstrNames.inc -gen-instr-enums) tablegen(SparcGenInstrInfo.inc -gen-instr-desc) diff --git a/lib/Target/Sparc/Makefile b/lib/Target/Sparc/Makefile index af7d9da..4ef1519 100644 --- a/lib/Target/Sparc/Makefile +++ b/lib/Target/Sparc/Makefile @@ -12,9 +12,7 @@ LIBRARYNAME = LLVMSparcCodeGen TARGET = Sparc # Make sure that tblgen is run, first thing. -BUILT_SOURCES = SparcGenRegisterInfo.h.inc SparcGenRegisterNames.inc \ - SparcGenRegisterInfo.inc SparcGenRegisterDesc.inc \ - SparcGenInstrNames.inc \ +BUILT_SOURCES = SparcGenRegisterInfo.inc SparcGenInstrNames.inc \ SparcGenInstrInfo.inc SparcGenAsmWriter.inc \ SparcGenDAGISel.inc SparcGenSubtarget.inc SparcGenCallingConv.inc diff --git a/lib/Target/Sparc/Sparc.h b/lib/Target/Sparc/Sparc.h index a37920d..0f03ca3 100644 --- a/lib/Target/Sparc/Sparc.h +++ b/lib/Target/Sparc/Sparc.h @@ -36,7 +36,8 @@ namespace llvm { // Defines symbolic names for Sparc registers. This defines a mapping from // register name to register number. // -#include "SparcGenRegisterNames.inc" +#define GET_REGINFO_ENUM +#include "SparcGenRegisterInfo.inc" // Defines symbolic names for the Sparc instructions. // diff --git a/lib/Target/Sparc/SparcRegisterInfo.cpp b/lib/Target/Sparc/SparcRegisterInfo.cpp index c63f52e..48ca15b 100644 --- a/lib/Target/Sparc/SparcRegisterInfo.cpp +++ b/lib/Target/Sparc/SparcRegisterInfo.cpp @@ -23,8 +23,11 @@ #include "llvm/Type.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" -#include "SparcGenRegisterDesc.inc" + +#define GET_REGINFO_MC_DESC +#define GET_REGINFO_TARGET_DESC #include "SparcGenRegisterInfo.inc" + using namespace llvm; SparcRegisterInfo::SparcRegisterInfo(SparcSubtarget &st, diff --git a/lib/Target/Sparc/SparcRegisterInfo.h b/lib/Target/Sparc/SparcRegisterInfo.h index 56c8068..ec9e63a 100644 --- a/lib/Target/Sparc/SparcRegisterInfo.h +++ b/lib/Target/Sparc/SparcRegisterInfo.h @@ -15,7 +15,9 @@ #define SPARCREGISTERINFO_H #include "llvm/Target/TargetRegisterInfo.h" -#include "SparcGenRegisterInfo.h.inc" + +#define GET_REGINFO_HEADER +#include "SparcGenRegisterInfo.inc" namespace llvm { diff --git a/lib/Target/SystemZ/CMakeLists.txt b/lib/Target/SystemZ/CMakeLists.txt index 3e06109..5adf5e3 100644 --- a/lib/Target/SystemZ/CMakeLists.txt +++ b/lib/Target/SystemZ/CMakeLists.txt @@ -1,8 +1,5 @@ set(LLVM_TARGET_DEFINITIONS SystemZ.td) -tablegen(SystemZGenRegisterNames.inc -gen-register-enums) -tablegen(SystemZGenRegisterDesc.inc -gen-register-desc) -tablegen(SystemZGenRegisterInfo.h.inc -gen-register-info-header) tablegen(SystemZGenRegisterInfo.inc -gen-register-info) tablegen(SystemZGenInstrNames.inc -gen-instr-enums) tablegen(SystemZGenInstrInfo.inc -gen-instr-desc) diff --git a/lib/Target/SystemZ/Makefile b/lib/Target/SystemZ/Makefile index 2481715..4b45615 100644 --- a/lib/Target/SystemZ/Makefile +++ b/lib/Target/SystemZ/Makefile @@ -12,9 +12,7 @@ LIBRARYNAME = LLVMSystemZCodeGen TARGET = SystemZ # Make sure that tblgen is run, first thing. -BUILT_SOURCES = SystemZGenRegisterInfo.h.inc SystemZGenRegisterNames.inc \ - SystemZGenRegisterInfo.inc SystemZGenRegisterDesc.inc \ - SystemZGenInstrNames.inc \ +BUILT_SOURCES = SystemZGenRegisterInfo.inc SystemZGenInstrNames.inc \ SystemZGenInstrInfo.inc SystemZGenAsmWriter.inc \ SystemZGenDAGISel.inc SystemZGenSubtarget.inc SystemZGenCallingConv.inc diff --git a/lib/Target/SystemZ/SystemZ.h b/lib/Target/SystemZ/SystemZ.h index ea5240a..8bf9fc5 100644 --- a/lib/Target/SystemZ/SystemZ.h +++ b/lib/Target/SystemZ/SystemZ.h @@ -53,7 +53,8 @@ namespace llvm { // Defines symbolic names for SystemZ registers. // This defines a mapping from register name to register number. -#include "SystemZGenRegisterNames.inc" +#define GET_REGINFO_ENUM +#include "SystemZGenRegisterInfo.inc" // Defines symbolic names for the SystemZ instructions. #include "SystemZGenInstrNames.inc" diff --git a/lib/Target/SystemZ/SystemZRegisterInfo.cpp b/lib/Target/SystemZ/SystemZRegisterInfo.cpp index a587e1c..b3c76dd 100644 --- a/lib/Target/SystemZ/SystemZRegisterInfo.cpp +++ b/lib/Target/SystemZ/SystemZRegisterInfo.cpp @@ -25,8 +25,11 @@ #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include "llvm/ADT/BitVector.h" -#include "SystemZGenRegisterDesc.inc" + +#define GET_REGINFO_MC_DESC +#define GET_REGINFO_TARGET_DESC #include "SystemZGenRegisterInfo.inc" + using namespace llvm; SystemZRegisterInfo::SystemZRegisterInfo(SystemZTargetMachine &tm, diff --git a/lib/Target/SystemZ/SystemZRegisterInfo.h b/lib/Target/SystemZ/SystemZRegisterInfo.h index cd8f20f..2e262e1 100644 --- a/lib/Target/SystemZ/SystemZRegisterInfo.h +++ b/lib/Target/SystemZ/SystemZRegisterInfo.h @@ -15,7 +15,9 @@ #define SystemZREGISTERINFO_H #include "llvm/Target/TargetRegisterInfo.h" -#include "SystemZGenRegisterInfo.h.inc" + +#define GET_REGINFO_HEADER +#include "SystemZGenRegisterInfo.inc" namespace llvm { diff --git a/lib/Target/X86/CMakeLists.txt b/lib/Target/X86/CMakeLists.txt index 7237ed8..31d69af 100644 --- a/lib/Target/X86/CMakeLists.txt +++ b/lib/Target/X86/CMakeLists.txt @@ -1,8 +1,5 @@ set(LLVM_TARGET_DEFINITIONS X86.td) -tablegen(X86GenRegisterNames.inc -gen-register-enums) -tablegen(X86GenRegisterDesc.inc -gen-register-desc) -tablegen(X86GenRegisterInfo.h.inc -gen-register-info-header) tablegen(X86GenRegisterInfo.inc -gen-register-info) tablegen(X86GenDisassemblerTables.inc -gen-disassembler) tablegen(X86GenInstrNames.inc -gen-instr-enums) diff --git a/lib/Target/X86/Disassembler/X86Disassembler.cpp b/lib/Target/X86/Disassembler/X86Disassembler.cpp index d8a105e..4a0d2ec 100644 --- a/lib/Target/X86/Disassembler/X86Disassembler.cpp +++ b/lib/Target/X86/Disassembler/X86Disassembler.cpp @@ -26,7 +26,8 @@ #include "llvm/Support/MemoryObject.h" #include "llvm/Support/raw_ostream.h" -#include "X86GenRegisterNames.inc" +#define GET_REGINFO_ENUM +#include "X86GenRegisterInfo.inc" #include "X86GenEDInfo.inc" using namespace llvm; diff --git a/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp b/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp index 68247d2..d01a600 100644 --- a/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp +++ b/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp @@ -27,12 +27,11 @@ using namespace llvm; // Include the auto-generated portion of the assembly writer. +#define GET_REGINFO_ENUM +#include "X86GenRegisterInfo.inc" #define GET_INSTRUCTION_NAME #define PRINT_ALIAS_INSTR -#include "X86GenRegisterNames.inc" #include "X86GenAsmWriter.inc" -#undef PRINT_ALIAS_INSTR -#undef GET_INSTRUCTION_NAME X86ATTInstPrinter::X86ATTInstPrinter(TargetMachine &TM, const MCAsmInfo &MAI) : MCInstPrinter(MAI) { diff --git a/lib/Target/X86/MCTargetDesc/X86TargetDesc.cpp b/lib/Target/X86/MCTargetDesc/X86TargetDesc.cpp index 8d61745..7aa77bd 100644 --- a/lib/Target/X86/MCTargetDesc/X86TargetDesc.cpp +++ b/lib/Target/X86/MCTargetDesc/X86TargetDesc.cpp @@ -14,7 +14,9 @@ #include "X86TargetDesc.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/Target/TargetRegistry.h" -#include "X86GenRegisterDesc.inc" + +#define GET_REGINFO_MC_DESC +#include "X86GenRegisterInfo.inc" using namespace llvm; MCRegisterInfo *createX86MCRegisterInfo() { diff --git a/lib/Target/X86/MCTargetDesc/X86TargetDesc.h b/lib/Target/X86/MCTargetDesc/X86TargetDesc.h index bcf851f..0d876dc 100644 --- a/lib/Target/X86/MCTargetDesc/X86TargetDesc.h +++ b/lib/Target/X86/MCTargetDesc/X86TargetDesc.h @@ -23,6 +23,7 @@ extern Target TheX86_32Target, TheX86_64Target; // Defines symbolic names for X86 registers. This defines a mapping from // register name to register number. // -#include "X86GenRegisterNames.inc" +#define GET_REGINFO_ENUM +#include "X86GenRegisterInfo.inc" #endif diff --git a/lib/Target/X86/Makefile b/lib/Target/X86/Makefile index 2102db7..fad8343 100644 --- a/lib/Target/X86/Makefile +++ b/lib/Target/X86/Makefile @@ -12,8 +12,7 @@ LIBRARYNAME = LLVMX86CodeGen TARGET = X86 # Make sure that tblgen is run, first thing. -BUILT_SOURCES = X86GenRegisterNames.inc X86GenRegisterDesc.inc \ - X86GenRegisterInfo.h.inc X86GenRegisterInfo.inc \ +BUILT_SOURCES = X86GenRegisterInfo.inc \ X86GenInstrNames.inc X86GenInstrInfo.inc \ X86GenAsmWriter.inc X86GenAsmMatcher.inc \ X86GenAsmWriter1.inc X86GenDAGISel.inc \ diff --git a/lib/Target/X86/X86RegisterInfo.cpp b/lib/Target/X86/X86RegisterInfo.cpp index c67da21..48f60f8 100644 --- a/lib/Target/X86/X86RegisterInfo.cpp +++ b/lib/Target/X86/X86RegisterInfo.cpp @@ -39,8 +39,11 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/CommandLine.h" -#include "X86GenRegisterDesc.inc" + +#define GET_REGINFO_MC_DESC +#define GET_REGINFO_TARGET_DESC #include "X86GenRegisterInfo.inc" + using namespace llvm; cl::opt diff --git a/lib/Target/X86/X86RegisterInfo.h b/lib/Target/X86/X86RegisterInfo.h index 9fd6ed5..0c014a6 100644 --- a/lib/Target/X86/X86RegisterInfo.h +++ b/lib/Target/X86/X86RegisterInfo.h @@ -15,7 +15,9 @@ #define X86REGISTERINFO_H #include "llvm/Target/TargetRegisterInfo.h" -#include "X86GenRegisterInfo.h.inc" + +#define GET_REGINFO_HEADER +#include "X86GenRegisterInfo.inc" namespace llvm { class Type; diff --git a/lib/Target/XCore/CMakeLists.txt b/lib/Target/XCore/CMakeLists.txt index 959e9a1..f6e7c20 100644 --- a/lib/Target/XCore/CMakeLists.txt +++ b/lib/Target/XCore/CMakeLists.txt @@ -1,8 +1,5 @@ set(LLVM_TARGET_DEFINITIONS XCore.td) -tablegen(XCoreGenRegisterNames.inc -gen-register-enums) -tablegen(XCoreGenRegisterDesc.inc -gen-register-desc) -tablegen(XCoreGenRegisterInfo.h.inc -gen-register-info-header) tablegen(XCoreGenRegisterInfo.inc -gen-register-info) tablegen(XCoreGenInstrNames.inc -gen-instr-enums) tablegen(XCoreGenInstrInfo.inc -gen-instr-desc) diff --git a/lib/Target/XCore/Makefile b/lib/Target/XCore/Makefile index f67ef51..ddc85dd 100644 --- a/lib/Target/XCore/Makefile +++ b/lib/Target/XCore/Makefile @@ -12,9 +12,7 @@ LIBRARYNAME = LLVMXCoreCodeGen TARGET = XCore # Make sure that tblgen is run, first thing. -BUILT_SOURCES = XCoreGenRegisterInfo.h.inc XCoreGenRegisterNames.inc \ - XCoreGenRegisterInfo.inc XCoreGenRegisterDesc.inc \ - XCoreGenInstrNames.inc \ +BUILT_SOURCES = XCoreGenRegisterInfo.inc XCoreGenInstrNames.inc \ XCoreGenInstrInfo.inc XCoreGenAsmWriter.inc \ XCoreGenDAGISel.inc XCoreGenCallingConv.inc \ XCoreGenSubtarget.inc diff --git a/lib/Target/XCore/XCore.h b/lib/Target/XCore/XCore.h index 8937fbe..69c343d 100644 --- a/lib/Target/XCore/XCore.h +++ b/lib/Target/XCore/XCore.h @@ -32,7 +32,8 @@ namespace llvm { // Defines symbolic names for XCore registers. This defines a mapping from // register name to register number. // -#include "XCoreGenRegisterNames.inc" +#define GET_REGINFO_ENUM +#include "XCoreGenRegisterInfo.inc" // Defines symbolic names for the XCore instructions. // diff --git a/lib/Target/XCore/XCoreRegisterInfo.cpp b/lib/Target/XCore/XCoreRegisterInfo.cpp index 966e33b..0c9473e 100644 --- a/lib/Target/XCore/XCoreRegisterInfo.cpp +++ b/lib/Target/XCore/XCoreRegisterInfo.cpp @@ -32,8 +32,11 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" -#include "XCoreGenRegisterDesc.inc" + +#define GET_REGINFO_MC_DESC +#define GET_REGINFO_TARGET_DESC #include "XCoreGenRegisterInfo.inc" + using namespace llvm; XCoreRegisterInfo::XCoreRegisterInfo(const TargetInstrInfo &tii) diff --git a/lib/Target/XCore/XCoreRegisterInfo.h b/lib/Target/XCore/XCoreRegisterInfo.h index 7a9bc9f..801d9eb 100644 --- a/lib/Target/XCore/XCoreRegisterInfo.h +++ b/lib/Target/XCore/XCoreRegisterInfo.h @@ -15,7 +15,9 @@ #define XCOREREGISTERINFO_H #include "llvm/Target/TargetRegisterInfo.h" -#include "XCoreGenRegisterInfo.h.inc" + +#define GET_REGINFO_HEADER +#include "XCoreGenRegisterInfo.inc" namespace llvm { diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp index 2fcb2d4..de20fb2 100644 --- a/utils/TableGen/RegisterInfoEmitter.cpp +++ b/utils/TableGen/RegisterInfoEmitter.cpp @@ -25,14 +25,18 @@ using namespace llvm; // runEnums - Print out enum values for all of the registers. -void RegisterInfoEmitter::runEnums(raw_ostream &OS) { - CodeGenTarget Target(Records); - CodeGenRegBank &Bank = Target.getRegBank(); +void +RegisterInfoEmitter::runEnums(raw_ostream &OS, + CodeGenTarget &Target, CodeGenRegBank &Bank) { const std::vector &Registers = Bank.getRegisters(); std::string Namespace = Registers[0]->TheDef->getValueAsString("Namespace"); EmitSourceFileHeader("Target Register Enum Values", OS); + + OS << "\n#ifdef GET_REGINFO_ENUM\n"; + OS << "#undef GET_REGINFO_ENUM\n"; + OS << "namespace llvm {\n\n"; if (!Namespace.empty()) @@ -63,12 +67,33 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS) { if (!Namespace.empty()) OS << "}\n"; } + + const std::vector &RegisterClasses = + Target.getRegisterClasses(); + + if (!RegisterClasses.empty()) { + OS << "\n// Register classes\n"; + OS << "namespace " << RegisterClasses[0].Namespace << " {\n"; + OS << "enum {\n"; + for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) { + if (i) OS << ",\n"; + OS << " " << RegisterClasses[i].getName() << "RegClassID"; + OS << " = " << i; + } + OS << "\n };\n"; + OS << "}\n"; + } + OS << "} // End llvm namespace \n"; + OS << "#endif // GET_REGINFO_ENUM\n\n"; } -void RegisterInfoEmitter::runHeader(raw_ostream &OS) { +void RegisterInfoEmitter::runHeader(raw_ostream &OS, CodeGenTarget &Target) { EmitSourceFileHeader("Register Information Header Fragment", OS); - CodeGenTarget Target(Records); + + OS << "\n#ifdef GET_REGINFO_HEADER\n"; + OS << "#undef GET_REGINFO_HEADER\n"; + const std::string &TargetName = Target.getName(); std::string ClassName = TargetName + "GenRegisterInfo"; @@ -100,14 +125,6 @@ void RegisterInfoEmitter::runHeader(raw_ostream &OS) { OS << "namespace " << RegisterClasses[0].Namespace << " { // Register classes\n"; - OS << " enum {\n"; - for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) { - if (i) OS << ",\n"; - OS << " " << RegisterClasses[i].getName() << "RegClassID"; - OS << " = " << i; - } - OS << "\n };\n\n"; - for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) { const CodeGenRegisterClass &RC = RegisterClasses[i]; const std::string &Name = RC.getName(); @@ -129,17 +146,125 @@ void RegisterInfoEmitter::runHeader(raw_ostream &OS) { OS << "} // end of namespace " << TargetName << "\n\n"; } OS << "} // End llvm namespace \n"; + OS << "#endif // GET_REGINFO_HEADER\n\n"; } // -// RegisterInfoEmitter::run - Main register file description emitter. +// runMCDesc - Print out MC register descriptions. // -void RegisterInfoEmitter::run(raw_ostream &OS) { - CodeGenTarget Target(Records); - CodeGenRegBank &RegBank = Target.getRegBank(); - RegBank.computeDerivedInfo(); +void +RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, + CodeGenRegBank &RegBank) { + EmitSourceFileHeader("MC Register Information", OS); + + OS << "\n#ifdef GET_REGINFO_MC_DESC\n"; + OS << "#undef GET_REGINFO_MC_DESC\n"; + + std::map Overlaps; + RegBank.computeOverlaps(Overlaps); + + OS << "namespace llvm {\n\n"; + + const std::string &TargetName = Target.getName(); + std::string ClassName = TargetName + "GenMCRegisterInfo"; + OS << "struct " << ClassName << " : public MCRegisterInfo {\n" + << " explicit " << ClassName << "(const MCRegisterDesc *D);\n"; + OS << "};\n"; + + OS << "\nnamespace {\n"; + + const std::vector &Regs = RegBank.getRegisters(); + + // Emit an overlap list for all registers. + for (unsigned i = 0, e = Regs.size(); i != e; ++i) { + const CodeGenRegister *Reg = Regs[i]; + const CodeGenRegister::Set &O = Overlaps[Reg]; + // Move Reg to the front so TRI::getAliasSet can share the list. + OS << " const unsigned " << Reg->getName() << "_Overlaps[] = { " + << getQualifiedName(Reg->TheDef) << ", "; + for (CodeGenRegister::Set::const_iterator I = O.begin(), E = O.end(); + I != E; ++I) + if (*I != Reg) + OS << getQualifiedName((*I)->TheDef) << ", "; + OS << "0 };\n"; + } + + // Emit the empty sub-registers list + OS << " const unsigned Empty_SubRegsSet[] = { 0 };\n"; + // Loop over all of the registers which have sub-registers, emitting the + // sub-registers list to memory. + for (unsigned i = 0, e = Regs.size(); i != e; ++i) { + const CodeGenRegister &Reg = *Regs[i]; + if (Reg.getSubRegs().empty()) + continue; + // getSubRegs() orders by SubRegIndex. We want a topological order. + SetVector SR; + Reg.addSubRegsPreOrder(SR); + OS << " const unsigned " << Reg.getName() << "_SubRegsSet[] = { "; + for (unsigned j = 0, je = SR.size(); j != je; ++j) + OS << getQualifiedName(SR[j]->TheDef) << ", "; + OS << "0 };\n"; + } + + // Emit the empty super-registers list + OS << " const unsigned Empty_SuperRegsSet[] = { 0 };\n"; + // Loop over all of the registers which have super-registers, emitting the + // super-registers list to memory. + for (unsigned i = 0, e = Regs.size(); i != e; ++i) { + const CodeGenRegister &Reg = *Regs[i]; + const CodeGenRegister::SuperRegList &SR = Reg.getSuperRegs(); + if (SR.empty()) + continue; + OS << " const unsigned " << Reg.getName() << "_SuperRegsSet[] = { "; + for (unsigned j = 0, je = SR.size(); j != je; ++j) + OS << getQualifiedName(SR[j]->TheDef) << ", "; + OS << "0 };\n"; + } + + OS << "\n const MCRegisterDesc " << TargetName + << "RegDesc[] = { // Descriptors\n"; + OS << " { \"NOREG\",\t0,\t0,\t0 },\n"; + + // Now that register alias and sub-registers sets have been emitted, emit the + // register descriptors now. + for (unsigned i = 0, e = Regs.size(); i != e; ++i) { + const CodeGenRegister &Reg = *Regs[i]; + OS << " { \""; + OS << Reg.getName() << "\",\t" << Reg.getName() << "_Overlaps,\t"; + if (!Reg.getSubRegs().empty()) + OS << Reg.getName() << "_SubRegsSet,\t"; + else + OS << "Empty_SubRegsSet,\t"; + if (!Reg.getSuperRegs().empty()) + OS << Reg.getName() << "_SuperRegsSet"; + else + OS << "Empty_SuperRegsSet"; + OS << " },\n"; + } + OS << " };\n"; // End of register descriptors... + + OS << "}\n\n"; // End of anonymous namespace... + + // MCRegisterInfo initialization routine. + OS << "static inline void Init" << TargetName + << "MCRegisterInfo(MCRegisterInfo *RI) {\n"; + OS << " RI->InitMCRegisterInfo(" << TargetName << "RegDesc, " + << Regs.size()+1 << ");\n}\n\n"; + + OS << "} // End llvm namespace \n"; + OS << "#endif // GET_REGINFO_MC_DESC\n\n"; +} - EmitSourceFileHeader("Register Information Source Fragment", OS); +// +// runTargetDesc - Output the target register and register file descriptions. +// +void +RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, + CodeGenRegBank &RegBank){ + EmitSourceFileHeader("Target Register and Register Classes Information", OS); + + OS << "\n#ifdef GET_REGINFO_TARGET_DESC\n"; + OS << "#undef GET_REGINFO_TARGET_DESC\n"; OS << "namespace llvm {\n\n"; @@ -614,102 +739,16 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { OS << " };\n}\n\n"; OS << "} // End llvm namespace \n"; + OS << "#endif // GET_REGINFO_TARGET_DESC\n\n"; } -void RegisterInfoEmitter::runDesc(raw_ostream &OS) { +void RegisterInfoEmitter::run(raw_ostream &OS) { CodeGenTarget Target(Records); CodeGenRegBank &RegBank = Target.getRegBank(); RegBank.computeDerivedInfo(); - std::map Overlaps; - RegBank.computeOverlaps(Overlaps); - - OS << "namespace llvm {\n\n"; - - const std::string &TargetName = Target.getName(); - std::string ClassName = TargetName + "GenMCRegisterInfo"; - OS << "struct " << ClassName << " : public MCRegisterInfo {\n" - << " explicit " << ClassName << "(const MCRegisterDesc *D);\n"; - OS << "};\n"; - OS << "\nnamespace {\n"; - - const std::vector &Regs = RegBank.getRegisters(); - - // Emit an overlap list for all registers. - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - const CodeGenRegister *Reg = Regs[i]; - const CodeGenRegister::Set &O = Overlaps[Reg]; - // Move Reg to the front so TRI::getAliasSet can share the list. - OS << " const unsigned " << Reg->getName() << "_Overlaps[] = { " - << getQualifiedName(Reg->TheDef) << ", "; - for (CodeGenRegister::Set::const_iterator I = O.begin(), E = O.end(); - I != E; ++I) - if (*I != Reg) - OS << getQualifiedName((*I)->TheDef) << ", "; - OS << "0 };\n"; - } - - // Emit the empty sub-registers list - OS << " const unsigned Empty_SubRegsSet[] = { 0 };\n"; - // Loop over all of the registers which have sub-registers, emitting the - // sub-registers list to memory. - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - const CodeGenRegister &Reg = *Regs[i]; - if (Reg.getSubRegs().empty()) - continue; - // getSubRegs() orders by SubRegIndex. We want a topological order. - SetVector SR; - Reg.addSubRegsPreOrder(SR); - OS << " const unsigned " << Reg.getName() << "_SubRegsSet[] = { "; - for (unsigned j = 0, je = SR.size(); j != je; ++j) - OS << getQualifiedName(SR[j]->TheDef) << ", "; - OS << "0 };\n"; - } - - // Emit the empty super-registers list - OS << " const unsigned Empty_SuperRegsSet[] = { 0 };\n"; - // Loop over all of the registers which have super-registers, emitting the - // super-registers list to memory. - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - const CodeGenRegister &Reg = *Regs[i]; - const CodeGenRegister::SuperRegList &SR = Reg.getSuperRegs(); - if (SR.empty()) - continue; - OS << " const unsigned " << Reg.getName() << "_SuperRegsSet[] = { "; - for (unsigned j = 0, je = SR.size(); j != je; ++j) - OS << getQualifiedName(SR[j]->TheDef) << ", "; - OS << "0 };\n"; - } - - OS << "\n const MCRegisterDesc " << TargetName - << "RegDesc[] = { // Descriptors\n"; - OS << " { \"NOREG\",\t0,\t0,\t0 },\n"; - - // Now that register alias and sub-registers sets have been emitted, emit the - // register descriptors now. - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - const CodeGenRegister &Reg = *Regs[i]; - OS << " { \""; - OS << Reg.getName() << "\",\t" << Reg.getName() << "_Overlaps,\t"; - if (!Reg.getSubRegs().empty()) - OS << Reg.getName() << "_SubRegsSet,\t"; - else - OS << "Empty_SubRegsSet,\t"; - if (!Reg.getSuperRegs().empty()) - OS << Reg.getName() << "_SuperRegsSet"; - else - OS << "Empty_SuperRegsSet"; - OS << " },\n"; - } - OS << " };\n"; // End of register descriptors... - - OS << "}\n\n"; // End of anonymous namespace... - - // MCRegisterInfo initialization routine. - OS << "static inline void Init" << TargetName - << "MCRegisterInfo(MCRegisterInfo *RI) {\n"; - OS << " RI->InitMCRegisterInfo(" << TargetName << "RegDesc, " - << Regs.size()+1 << ");\n}\n\n"; - - OS << "} // End llvm namespace \n"; + runEnums(OS, Target, RegBank); + runHeader(OS, Target); + runMCDesc(OS, Target, RegBank); + runTargetDesc(OS, Target, RegBank); } diff --git a/utils/TableGen/RegisterInfoEmitter.h b/utils/TableGen/RegisterInfoEmitter.h index 6bf14b2..d625b7d 100644 --- a/utils/TableGen/RegisterInfoEmitter.h +++ b/utils/TableGen/RegisterInfoEmitter.h @@ -20,22 +20,28 @@ namespace llvm { +class CodeGenRegBank; +class CodeGenTarget; + class RegisterInfoEmitter : public TableGenBackend { RecordKeeper &Records; public: RegisterInfoEmitter(RecordKeeper &R) : Records(R) {} - // run - Output the register file description, returning true on failure. - void run(raw_ostream &o); + // runEnums - Print out enum values for all of the registers. + void runEnums(raw_ostream &o, CodeGenTarget &Target, CodeGenRegBank &Bank); // runHeader - Emit a header fragment for the register info emitter. - void runHeader(raw_ostream &o); + void runHeader(raw_ostream &o, CodeGenTarget &Target); - // runEnums - Print out enum values for all of the registers. - void runEnums(raw_ostream &o); + // runMCDesc - Print out MC register descriptions. + void runMCDesc(raw_ostream &o, CodeGenTarget &Target, CodeGenRegBank &Bank); + + // runTargetDesc - Output the target register and register file descriptions. + void runTargetDesc(raw_ostream &o, CodeGenTarget &Target, CodeGenRegBank &Bank); - // runDesc - Print out register descriptions. - void runDesc(raw_ostream &o); + // run - Output the register file description. + void run(raw_ostream &o); }; } // End llvm namespace diff --git a/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp index b11ef6f..6f220c9 100644 --- a/utils/TableGen/TableGen.cpp +++ b/utils/TableGen/TableGen.cpp @@ -54,7 +54,7 @@ using namespace llvm; enum ActionType { PrintRecords, GenEmitter, - GenRegisterEnums, GenRegisterDesc, GenRegisterInfo, GenRegisterInfoHeader, + GenRegisterInfo, GenInstrEnums, GenInstrs, GenAsmWriter, GenAsmMatcher, GenARMDecoder, GenDisassembler, @@ -93,14 +93,8 @@ namespace { "Print all records to stdout (default)"), clEnumValN(GenEmitter, "gen-emitter", "Generate machine code emitter"), - clEnumValN(GenRegisterEnums, "gen-register-enums", - "Generate enum values for registers"), - clEnumValN(GenRegisterDesc, "gen-register-desc", - "Generate register descriptions"), clEnumValN(GenRegisterInfo, "gen-register-info", - "Generate registers & reg-classes info"), - clEnumValN(GenRegisterInfoHeader, "gen-register-info-header", - "Generate registers & reg-classes info header"), + "Generate registers and register classes info"), clEnumValN(GenInstrEnums, "gen-instr-enums", "Generate enum values for instructions"), clEnumValN(GenInstrs, "gen-instr-desc", @@ -263,18 +257,9 @@ int main(int argc, char **argv) { case GenEmitter: CodeEmitterGen(Records).run(Out.os()); break; - case GenRegisterEnums: - RegisterInfoEmitter(Records).runEnums(Out.os()); - break; - case GenRegisterDesc: - RegisterInfoEmitter(Records).runDesc(Out.os()); - break; case GenRegisterInfo: RegisterInfoEmitter(Records).run(Out.os()); break; - case GenRegisterInfoHeader: - RegisterInfoEmitter(Records).runHeader(Out.os()); - break; case GenInstrEnums: InstrEnumEmitter(Records).run(Out.os()); break; -- cgit v1.1 From 702110159a53481227b01fed81fa4eec0ad3cc46 Mon Sep 17 00:00:00 2001 From: Owen Anderson Date: Mon, 27 Jun 2011 18:34:12 +0000 Subject: The index stored in the RegDefIter is one after the current index. When getting the index, decrement it so that it points to the current element. Fixes an off-by-one bug encountered when trying to make use of MVT::untyped. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133923 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h index 3ad2bd6..9c27b2e 100644 --- a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h +++ b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h @@ -140,7 +140,7 @@ namespace llvm { } unsigned GetIdx() const { - return DefIdx; + return DefIdx-1; } void Advance(); -- cgit v1.1 From 0ff9220ccb6ef419ba4d3a4daf98f4658a9e5134 Mon Sep 17 00:00:00 2001 From: Jim Grosbach Date: Mon, 27 Jun 2011 19:09:15 +0000 Subject: ARM Assembly syntax support for arithmetic implied dest operand. When the destination operand is the same as the first source register operand for arithmetic instructions, the destination operand may be omitted. For example, the following two instructions are equivalent: sub r2, r2, #6 sub r2, #6 rdar://9682597 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133925 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMInstrInfo.td | 32 +++++++-- test/MC/ARM/arm-arithmetic-aliases.s | 126 +++++++++++++++++++++++++++++++++++ 2 files changed, 151 insertions(+), 7 deletions(-) create mode 100644 test/MC/ARM/arm-arithmetic-aliases.s diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index 5c013de..b34b127 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -676,7 +676,7 @@ include "ARMInstrFormats.td" /// binop that produces a value. multiclass AsI1_bin_irs opcod, string opc, InstrItinClass iii, InstrItinClass iir, InstrItinClass iis, - PatFrag opnode, bit Commutable = 0> { + PatFrag opnode, string baseOpc, bit Commutable = 0> { // The register-immediate version is re-materializable. This is useful // in particular for taking the address of a local. let isReMaterializable = 1 in { @@ -716,6 +716,24 @@ multiclass AsI1_bin_irs opcod, string opc, let Inst{15-12} = Rd; let Inst{11-0} = shift; } + + // Assembly aliases for optional destination operand when it's the same + // as the source operand. + def : InstAlias(!strconcat(baseOpc, "ri")) GPR:$Rdn, GPR:$Rdn, + so_imm:$imm, pred:$p, + cc_out:$s)>, + Requires<[IsARM]>; + def : InstAlias(!strconcat(baseOpc, "rr")) GPR:$Rdn, GPR:$Rdn, + GPR:$Rm, pred:$p, + cc_out:$s)>, + Requires<[IsARM]>; + def : InstAlias(!strconcat(baseOpc, "rs")) GPR:$Rdn, GPR:$Rdn, + so_reg:$shift, pred:$p, + cc_out:$s)>, + Requires<[IsARM]>; } /// AI1_bin_s_irs - Similar to AsI1_bin_irs except it sets the 's' bit so the @@ -2205,10 +2223,10 @@ def UBFX : I<(outs GPR:$Rd), defm ADD : AsI1_bin_irs<0b0100, "add", IIC_iALUi, IIC_iALUr, IIC_iALUsr, - BinOpFrag<(add node:$LHS, node:$RHS)>, 1>; + BinOpFrag<(add node:$LHS, node:$RHS)>, "ADD", 1>; defm SUB : AsI1_bin_irs<0b0010, "sub", IIC_iALUi, IIC_iALUr, IIC_iALUsr, - BinOpFrag<(sub node:$LHS, node:$RHS)>>; + BinOpFrag<(sub node:$LHS, node:$RHS)>, "SUB">; // ADD and SUB with 's' bit set. defm ADDS : AI1_bin_s_irs<0b0100, "adds", @@ -2531,16 +2549,16 @@ def : ARMV6Pat<(int_arm_usat GPR:$a, imm:$pos), (USAT imm:$pos, GPR:$a, 0)>; defm AND : AsI1_bin_irs<0b0000, "and", IIC_iBITi, IIC_iBITr, IIC_iBITsr, - BinOpFrag<(and node:$LHS, node:$RHS)>, 1>; + BinOpFrag<(and node:$LHS, node:$RHS)>, "AND", 1>; defm ORR : AsI1_bin_irs<0b1100, "orr", IIC_iBITi, IIC_iBITr, IIC_iBITsr, - BinOpFrag<(or node:$LHS, node:$RHS)>, 1>; + BinOpFrag<(or node:$LHS, node:$RHS)>, "ORR", 1>; defm EOR : AsI1_bin_irs<0b0001, "eor", IIC_iBITi, IIC_iBITr, IIC_iBITsr, - BinOpFrag<(xor node:$LHS, node:$RHS)>, 1>; + BinOpFrag<(xor node:$LHS, node:$RHS)>, "EOR", 1>; defm BIC : AsI1_bin_irs<0b1110, "bic", IIC_iBITi, IIC_iBITr, IIC_iBITsr, - BinOpFrag<(and node:$LHS, (not node:$RHS))>>; + BinOpFrag<(and node:$LHS, (not node:$RHS))>, "BIC">; def BFC : I<(outs GPR:$Rd), (ins GPR:$src, bf_inv_mask_imm:$imm), AddrMode1, Size4Bytes, IndexModeNone, DPFrm, IIC_iUNAsi, diff --git a/test/MC/ARM/arm-arithmetic-aliases.s b/test/MC/ARM/arm-arithmetic-aliases.s new file mode 100644 index 0000000..9895cfc --- /dev/null +++ b/test/MC/ARM/arm-arithmetic-aliases.s @@ -0,0 +1,126 @@ +@ RUN: llvm-mc -triple arm-unknown-unknown -show-encoding < %s | FileCheck %s + +foo: +@ CHECK: foo + +sub r2, r2, #6 +sub r2, #6 +sub r2, r2, r3 +sub r2, r3 + +@ CHECK: sub r2, r2, #6 @ encoding: [0x06,0x20,0x42,0xe2] +@ CHECK: sub r2, r2, #6 @ encoding: [0x06,0x20,0x42,0xe2] +@ CHECK: sub r2, r2, r3 @ encoding: [0x03,0x20,0x42,0xe0] +@ CHECK: sub r2, r2, r3 @ encoding: [0x03,0x20,0x42,0xe0] + +add r2, r2, #6 +add r2, #6 +add r2, r2, r3 +add r2, r3 + +@ CHECK: add r2, r2, #6 @ encoding: [0x06,0x20,0x82,0xe2] +@ CHECK: add r2, r2, #6 @ encoding: [0x06,0x20,0x82,0xe2] +@ CHECK: add r2, r2, r3 @ encoding: [0x03,0x20,0x82,0xe0] +@ CHECK: add r2, r2, r3 @ encoding: [0x03,0x20,0x82,0xe0] + +and r2, r2, #6 +and r2, #6 +and r2, r2, r3 +and r2, r3 + +@ CHECK: and r2, r2, #6 @ encoding: [0x06,0x20,0x02,0xe2] +@ CHECK: and r2, r2, #6 @ encoding: [0x06,0x20,0x02,0xe2] +@ CHECK: and r2, r2, r3 @ encoding: [0x03,0x20,0x02,0xe0] +@ CHECK: and r2, r2, r3 @ encoding: [0x03,0x20,0x02,0xe0] + +orr r2, r2, #6 +orr r2, #6 +orr r2, r2, r3 +orr r2, r3 + +@ CHECK: orr r2, r2, #6 @ encoding: [0x06,0x20,0x82,0xe3] +@ CHECK: orr r2, r2, #6 @ encoding: [0x06,0x20,0x82,0xe3] +@ CHECK: orr r2, r2, r3 @ encoding: [0x03,0x20,0x82,0xe1] +@ CHECK: orr r2, r2, r3 @ encoding: [0x03,0x20,0x82,0xe1] + +eor r2, r2, #6 +eor r2, #6 +eor r2, r2, r3 +eor r2, r3 + +@ CHECK: eor r2, r2, #6 @ encoding: [0x06,0x20,0x22,0xe2] +@ CHECK: eor r2, r2, #6 @ encoding: [0x06,0x20,0x22,0xe2] +@ CHECK: eor r2, r2, r3 @ encoding: [0x03,0x20,0x22,0xe0] +@ CHECK: eor r2, r2, r3 @ encoding: [0x03,0x20,0x22,0xe0] + +bic r2, r2, #6 +bic r2, #6 +bic r2, r2, r3 +bic r2, r3 + +@ CHECK: bic r2, r2, #6 @ encoding: [0x06,0x20,0xc2,0xe3] +@ CHECK: bic r2, r2, #6 @ encoding: [0x06,0x20,0xc2,0xe3] +@ CHECK: bic r2, r2, r3 @ encoding: [0x03,0x20,0xc2,0xe1] +@ CHECK: bic r2, r2, r3 @ encoding: [0x03,0x20,0xc2,0xe1] + + +@ Also check that we handle the predicate and cc_out operands. +subseq r2, r2, #6 +subseq r2, #6 +subseq r2, r2, r3 +subseq r2, r3 + +@ CHECK: subseq r2, r2, #6 @ encoding: [0x06,0x20,0x52,0x02] +@ CHECK: subseq r2, r2, #6 @ encoding: [0x06,0x20,0x52,0x02] +@ CHECK: subseq r2, r2, r3 @ encoding: [0x03,0x20,0x52,0x00] +@ CHECK: subseq r2, r2, r3 @ encoding: [0x03,0x20,0x52,0x00] + +addseq r2, r2, #6 +addseq r2, #6 +addseq r2, r2, r3 +addseq r2, r3 + +@ CHECK: addseq r2, r2, #6 @ encoding: [0x06,0x20,0x92,0x02] +@ CHECK: addseq r2, r2, #6 @ encoding: [0x06,0x20,0x92,0x02] +@ CHECK: addseq r2, r2, r3 @ encoding: [0x03,0x20,0x92,0x00] +@ CHECK: addseq r2, r2, r3 @ encoding: [0x03,0x20,0x92,0x00] + +andseq r2, r2, #6 +andseq r2, #6 +andseq r2, r2, r3 +andseq r2, r3 + +@ CHECK: andseq r2, r2, #6 @ encoding: [0x06,0x20,0x12,0x02] +@ CHECK: andseq r2, r2, #6 @ encoding: [0x06,0x20,0x12,0x02] +@ CHECK: andseq r2, r2, r3 @ encoding: [0x03,0x20,0x12,0x00] +@ CHECK: andseq r2, r2, r3 @ encoding: [0x03,0x20,0x12,0x00] + +orrseq r2, r2, #6 +orrseq r2, #6 +orrseq r2, r2, r3 +orrseq r2, r3 + +@ CHECK: orrseq r2, r2, #6 @ encoding: [0x06,0x20,0x92,0x03] +@ CHECK: orrseq r2, r2, #6 @ encoding: [0x06,0x20,0x92,0x03] +@ CHECK: orrseq r2, r2, r3 @ encoding: [0x03,0x20,0x92,0x01] +@ CHECK: orrseq r2, r2, r3 @ encoding: [0x03,0x20,0x92,0x01] + +eorseq r2, r2, #6 +eorseq r2, #6 +eorseq r2, r2, r3 +eorseq r2, r3 + +@ CHECK: eorseq r2, r2, #6 @ encoding: [0x06,0x20,0x32,0x02] +@ CHECK: eorseq r2, r2, #6 @ encoding: [0x06,0x20,0x32,0x02] +@ CHECK: eorseq r2, r2, r3 @ encoding: [0x03,0x20,0x32,0x00] +@ CHECK: eorseq r2, r2, r3 @ encoding: [0x03,0x20,0x32,0x00] + +bicseq r2, r2, #6 +bicseq r2, #6 +bicseq r2, r2, r3 +bicseq r2, r3 + +@ CHECK: bicseq r2, r2, #6 @ encoding: [0x06,0x20,0xd2,0x03] +@ CHECK: bicseq r2, r2, #6 @ encoding: [0x06,0x20,0xd2,0x03] +@ CHECK: bicseq r2, r2, r3 @ encoding: [0x03,0x20,0xd2,0x01] +@ CHECK: bicseq r2, r2, r3 @ encoding: [0x03,0x20,0xd2,0x01] -- cgit v1.1 From ebbbfd0e2eeeb5b1a15f0e655a0a2119510713d4 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Mon, 27 Jun 2011 19:24:13 +0000 Subject: More refactoring. MC doesn't need know about subreg indices. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133927 91177308-0d34-0410-b5e6-96231b3b80d8 --- utils/TableGen/RegisterInfoEmitter.cpp | 157 +++++++++++++++++---------------- utils/TableGen/RegisterInfoEmitter.h | 10 ++- 2 files changed, 85 insertions(+), 82 deletions(-) diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp index de20fb2..ab081eb 100644 --- a/utils/TableGen/RegisterInfoEmitter.cpp +++ b/utils/TableGen/RegisterInfoEmitter.cpp @@ -53,24 +53,8 @@ RegisterInfoEmitter::runEnums(raw_ostream &OS, if (!Namespace.empty()) OS << "}\n"; - const std::vector &SubRegIndices = Bank.getSubRegIndices(); - if (!SubRegIndices.empty()) { - OS << "\n// Subregister indices\n"; - Namespace = SubRegIndices[0]->getValueAsString("Namespace"); - if (!Namespace.empty()) - OS << "namespace " << Namespace << " {\n"; - OS << "enum {\n NoSubRegister,\n"; - for (unsigned i = 0, e = Bank.getNumNamedIndices(); i != e; ++i) - OS << " " << SubRegIndices[i]->getName() << ",\t// " << i+1 << "\n"; - OS << " NUM_TARGET_NAMED_SUBREGS = " << SubRegIndices.size()+1 << "\n"; - OS << "};\n"; - if (!Namespace.empty()) - OS << "}\n"; - } - const std::vector &RegisterClasses = Target.getRegisterClasses(); - if (!RegisterClasses.empty()) { OS << "\n// Register classes\n"; OS << "namespace " << RegisterClasses[0].Namespace << " {\n"; @@ -88,67 +72,6 @@ RegisterInfoEmitter::runEnums(raw_ostream &OS, OS << "#endif // GET_REGINFO_ENUM\n\n"; } -void RegisterInfoEmitter::runHeader(raw_ostream &OS, CodeGenTarget &Target) { - EmitSourceFileHeader("Register Information Header Fragment", OS); - - OS << "\n#ifdef GET_REGINFO_HEADER\n"; - OS << "#undef GET_REGINFO_HEADER\n"; - - const std::string &TargetName = Target.getName(); - std::string ClassName = TargetName + "GenRegisterInfo"; - - OS << "#include \"llvm/Target/TargetRegisterInfo.h\"\n"; - OS << "#include \n\n"; - - OS << "namespace llvm {\n\n"; - - OS << "struct " << ClassName << " : public TargetRegisterInfo {\n" - << " explicit " << ClassName - << "(const MCRegisterDesc *D, const TargetRegisterInfoDesc *ID, " - << "int CallFrameSetupOpcode = -1, int CallFrameDestroyOpcode = -1);\n" - << " virtual int getDwarfRegNumFull(unsigned RegNum, " - << "unsigned Flavour) const;\n" - << " virtual int getLLVMRegNumFull(unsigned DwarfRegNum, " - << "unsigned Flavour) const;\n" - << " virtual int getDwarfRegNum(unsigned RegNum, bool isEH) const = 0;\n" - << " virtual bool needsStackRealignment(const MachineFunction &) const\n" - << " { return false; }\n" - << " unsigned getSubReg(unsigned RegNo, unsigned Index) const;\n" - << " unsigned getSubRegIndex(unsigned RegNo, unsigned SubRegNo) const;\n" - << " unsigned composeSubRegIndices(unsigned, unsigned) const;\n" - << "};\n\n"; - - const std::vector &RegisterClasses = - Target.getRegisterClasses(); - - if (!RegisterClasses.empty()) { - OS << "namespace " << RegisterClasses[0].Namespace - << " { // Register classes\n"; - - for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) { - const CodeGenRegisterClass &RC = RegisterClasses[i]; - const std::string &Name = RC.getName(); - - // Output the register class definition. - OS << " struct " << Name << "Class : public TargetRegisterClass {\n" - << " " << Name << "Class();\n"; - if (!RC.AltOrderSelect.empty()) - OS << " ArrayRef " - "getRawAllocationOrder(const MachineFunction&) const;\n"; - OS << " };\n"; - - // Output the extern for the instance. - OS << " extern " << Name << "Class\t" << Name << "RegClass;\n"; - // Output the extern for the pointer to the instance (should remove). - OS << " static TargetRegisterClass * const "<< Name <<"RegisterClass = &" - << Name << "RegClass;\n"; - } - OS << "} // end of namespace " << TargetName << "\n\n"; - } - OS << "} // End llvm namespace \n"; - OS << "#endif // GET_REGINFO_HEADER\n\n"; -} - // // runMCDesc - Print out MC register descriptions. // @@ -255,6 +178,84 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, OS << "#endif // GET_REGINFO_MC_DESC\n\n"; } +void +RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target, + CodeGenRegBank &RegBank) { + EmitSourceFileHeader("Register Information Header Fragment", OS); + + OS << "\n#ifdef GET_REGINFO_HEADER\n"; + OS << "#undef GET_REGINFO_HEADER\n"; + + const std::string &TargetName = Target.getName(); + std::string ClassName = TargetName + "GenRegisterInfo"; + + OS << "#include \"llvm/Target/TargetRegisterInfo.h\"\n"; + OS << "#include \n\n"; + + OS << "namespace llvm {\n\n"; + + OS << "struct " << ClassName << " : public TargetRegisterInfo {\n" + << " explicit " << ClassName + << "(const MCRegisterDesc *D, const TargetRegisterInfoDesc *ID, " + << "int CallFrameSetupOpcode = -1, int CallFrameDestroyOpcode = -1);\n" + << " virtual int getDwarfRegNumFull(unsigned RegNum, " + << "unsigned Flavour) const;\n" + << " virtual int getLLVMRegNumFull(unsigned DwarfRegNum, " + << "unsigned Flavour) const;\n" + << " virtual int getDwarfRegNum(unsigned RegNum, bool isEH) const = 0;\n" + << " virtual bool needsStackRealignment(const MachineFunction &) const\n" + << " { return false; }\n" + << " unsigned getSubReg(unsigned RegNo, unsigned Index) const;\n" + << " unsigned getSubRegIndex(unsigned RegNo, unsigned SubRegNo) const;\n" + << " unsigned composeSubRegIndices(unsigned, unsigned) const;\n" + << "};\n\n"; + + const std::vector &SubRegIndices = RegBank.getSubRegIndices(); + if (!SubRegIndices.empty()) { + OS << "\n// Subregister indices\n"; + std::string Namespace = SubRegIndices[0]->getValueAsString("Namespace"); + if (!Namespace.empty()) + OS << "namespace " << Namespace << " {\n"; + OS << "enum {\n NoSubRegister,\n"; + for (unsigned i = 0, e = RegBank.getNumNamedIndices(); i != e; ++i) + OS << " " << SubRegIndices[i]->getName() << ",\t// " << i+1 << "\n"; + OS << " NUM_TARGET_NAMED_SUBREGS = " << SubRegIndices.size()+1 << "\n"; + OS << "};\n"; + if (!Namespace.empty()) + OS << "}\n"; + } + + const std::vector &RegisterClasses = + Target.getRegisterClasses(); + + if (!RegisterClasses.empty()) { + OS << "namespace " << RegisterClasses[0].Namespace + << " { // Register classes\n"; + + for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) { + const CodeGenRegisterClass &RC = RegisterClasses[i]; + const std::string &Name = RC.getName(); + + // Output the register class definition. + OS << " struct " << Name << "Class : public TargetRegisterClass {\n" + << " " << Name << "Class();\n"; + if (!RC.AltOrderSelect.empty()) + OS << " ArrayRef " + "getRawAllocationOrder(const MachineFunction&) const;\n"; + OS << " };\n"; + + // Output the extern for the instance. + OS << " extern " << Name << "Class\t" << Name << "RegClass;\n"; + // Output the extern for the pointer to the instance (should remove). + OS << " static TargetRegisterClass * const "<< Name <<"RegisterClass = &" + << Name << "RegClass;\n"; + } + OS << "} // end of namespace " << TargetName << "\n\n"; + } + OS << "} // End llvm namespace \n"; + OS << "#endif // GET_REGINFO_HEADER\n\n"; +} + // // runTargetDesc - Output the target register and register file descriptions. // @@ -748,7 +749,7 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { RegBank.computeDerivedInfo(); runEnums(OS, Target, RegBank); - runHeader(OS, Target); runMCDesc(OS, Target, RegBank); + runTargetHeader(OS, Target, RegBank); runTargetDesc(OS, Target, RegBank); } diff --git a/utils/TableGen/RegisterInfoEmitter.h b/utils/TableGen/RegisterInfoEmitter.h index d625b7d..2c01b5c 100644 --- a/utils/TableGen/RegisterInfoEmitter.h +++ b/utils/TableGen/RegisterInfoEmitter.h @@ -31,14 +31,16 @@ public: // runEnums - Print out enum values for all of the registers. void runEnums(raw_ostream &o, CodeGenTarget &Target, CodeGenRegBank &Bank); - // runHeader - Emit a header fragment for the register info emitter. - void runHeader(raw_ostream &o, CodeGenTarget &Target); - // runMCDesc - Print out MC register descriptions. void runMCDesc(raw_ostream &o, CodeGenTarget &Target, CodeGenRegBank &Bank); + // runTargetHeader - Emit a header fragment for the register info emitter. + void runTargetHeader(raw_ostream &o, CodeGenTarget &Target, + CodeGenRegBank &Bank); + // runTargetDesc - Output the target register and register file descriptions. - void runTargetDesc(raw_ostream &o, CodeGenTarget &Target, CodeGenRegBank &Bank); + void runTargetDesc(raw_ostream &o, CodeGenTarget &Target, + CodeGenRegBank &Bank); // run - Output the register file description. void run(raw_ostream &o); -- cgit v1.1 From 2ca7f4d2f3782db8b9f1a264fc558a72b0fd4fa0 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Mon, 27 Jun 2011 19:41:39 +0000 Subject: Rename unnecessary forward declaration. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133928 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Target/TargetRegisterInfo.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h index d50bfe7..94cfd8b 100644 --- a/include/llvm/Target/TargetRegisterInfo.h +++ b/include/llvm/Target/TargetRegisterInfo.h @@ -28,7 +28,6 @@ namespace llvm { class BitVector; class MachineFunction; -class MachineMove; class RegScavenger; template class SmallVectorImpl; class raw_ostream; -- cgit v1.1 From 0d06bb954881dc7ff0e2333d5a3e249b7bb304d0 Mon Sep 17 00:00:00 2001 From: Jim Grosbach Date: Mon, 27 Jun 2011 20:00:07 +0000 Subject: ARM assembler support for vpush/vpop. Add aliases for the vpush/vpop mnemonics to the VFP load/store multiple writeback instructions w/ SP as the base pointer. rdar://9683231 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133932 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMInstrVFP.td | 9 +++++++++ test/MC/ARM/vpush-vpop.s | 19 +++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 test/MC/ARM/vpush-vpop.s diff --git a/lib/Target/ARM/ARMInstrVFP.td b/lib/Target/ARM/ARMInstrVFP.td index b4c3239..d2aaa97 100644 --- a/lib/Target/ARM/ARMInstrVFP.td +++ b/lib/Target/ARM/ARMInstrVFP.td @@ -166,6 +166,15 @@ defm VSTM : vfp_ldst_mult<"vstm", 0, IIC_fpLoad_m, IIC_fpLoad_mu>; def : MnemonicAlias<"vldm", "vldmia">; def : MnemonicAlias<"vstm", "vstmia">; +def : InstAlias<"vpush${p} $r", (VSTMDDB_UPD SP, pred:$p, dpr_reglist:$r)>, + Requires<[HasVFP2]>; +def : InstAlias<"vpush${p} $r", (VSTMSDB_UPD SP, pred:$p, spr_reglist:$r)>, + Requires<[HasVFP2]>; +def : InstAlias<"vpop${p} $r", (VLDMDIA_UPD SP, pred:$p, dpr_reglist:$r)>, + Requires<[HasVFP2]>; +def : InstAlias<"vpop${p} $r", (VLDMSIA_UPD SP, pred:$p, spr_reglist:$r)>, + Requires<[HasVFP2]>; + // FLDMX, FSTMX - mixing S/D registers for pre-armv6 cores //===----------------------------------------------------------------------===// diff --git a/test/MC/ARM/vpush-vpop.s b/test/MC/ARM/vpush-vpop.s new file mode 100644 index 0000000..1212c83 --- /dev/null +++ b/test/MC/ARM/vpush-vpop.s @@ -0,0 +1,19 @@ +@ RUN: llvm-mc -triple armv7-unknown-unknown -show-encoding < %s | FileCheck --check-prefix=CHECK-ARM %s +@ RUN: llvm-mc -triple thumbv7-unknown-unknown -show-encoding < %s | FileCheck --check-prefix=CHECK-THUMB %s + +foo: +@ CHECK: foo + vpush {d8, d9, d10, d11, d12} + vpush {s8, s9, s10, s11, s12} + vpop {d8, d9, d10, d11, d12} + vpop {s8, s9, s10, s11, s12} + +@ CHECK-THUMB: vpush {d8, d9, d10, d11, d12} @ encoding: [0x2d,0xed,0x0a,0x8b] +@ CHECK-THUMB: vpush {s8, s9, s10, s11, s12} @ encoding: [0x2d,0xed,0x05,0x4a] +@ CHECK-THUMB: vpop {d8, d9, d10, d11, d12} @ encoding: [0xbd,0xec,0x0a,0x8b] +@ CHECK-THUMB: vpop {s8, s9, s10, s11, s12} @ encoding: [0xbd,0xec,0x05,0x4a] + +@ CHECK-ARM: vpush {d8, d9, d10, d11, d12} @ encoding: [0x0a,0x8b,0x2d,0xed] +@ CHECK-ARM: vpush {s8, s9, s10, s11, s12} @ encoding: [0x05,0x4a,0x2d,0xed] +@ CHECK-ARM: vpop {d8, d9, d10, d11, d12} @ encoding: [0x0a,0x8b,0xbd,0xec] +@ CHECK-ARM: vpop {s8, s9, s10, s11, s12} @ encoding: [0x05,0x4a,0xbd,0xec] -- cgit v1.1 From 34720e193f55458c13de017f628f636aca9d768e Mon Sep 17 00:00:00 2001 From: Eric Christopher Date: Mon, 27 Jun 2011 20:31:01 +0000 Subject: Allow lr in the register options here. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133935 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/CodeGen/ARM/arm-modifier.ll | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/CodeGen/ARM/arm-modifier.ll b/test/CodeGen/ARM/arm-modifier.ll index 0a7bb6c..396de37 100644 --- a/test/CodeGen/ARM/arm-modifier.ll +++ b/test/CodeGen/ARM/arm-modifier.ll @@ -46,9 +46,9 @@ ret void define void @f3() nounwind { entry: ; CHECK: f3 -; CHECK: stm r{{[0-9]+}}, {[[REG1:(r[0-9]+)]], r{{[0-9]+}}} -; CHECK: adds lr, [[REG1]] -; CHECK: ldm r{{[0-9]+}}, {r{{[0-9]+}}, r{{[0-9]+}}} +; CHECK: stm {{lr|r[0-9]+}}, {[[REG1:(r[0-9]+)]], r{{[0-9]+}}} +; CHECK: adds {{lr|r[0-9]+}}, [[REG1]] +; CHECK: ldm {{lr|r[0-9]+}}, {r{{[0-9]+}}, r{{[0-9]+}}} %tmp = load i64* @f3_var, align 4 %tmp1 = load i64* @f3_var2, align 4 %0 = call i64 asm sideeffect "stm ${0:m}, ${1:M}\0A\09adds $3, $1\0A\09", "=*m,=r,1,r"(i64** @f3_ptr, i64 %tmp, i64 %tmp1) nounwind -- cgit v1.1 From fbd01783a67dd2bedd8197308ef00d4ad767fcd3 Mon Sep 17 00:00:00 2001 From: Jim Grosbach Date: Mon, 27 Jun 2011 20:32:18 +0000 Subject: ARM assembler support for ldmfd/stmfd mnemonics. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133936 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMInstrInfo.td | 2 ++ test/MC/ARM/arm_instructions.s | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index b34b127..cdb1fe0 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -2006,6 +2006,8 @@ defm STM : arm_ldst_mult<"stm", 0, LdStMulFrm, IIC_iStore_m, IIC_iStore_mu>; } // neverHasSideEffects // Load / Store Multiple Mnemonic Aliases +def : MnemonicAlias<"ldmfd", "ldmia">; +def : MnemonicAlias<"stmfd", "stmdb">; def : MnemonicAlias<"ldm", "ldmia">; def : MnemonicAlias<"stm", "stmia">; diff --git a/test/MC/ARM/arm_instructions.s b/test/MC/ARM/arm_instructions.s index f789441..66fc87f3 100644 --- a/test/MC/ARM/arm_instructions.s +++ b/test/MC/ARM/arm_instructions.s @@ -21,22 +21,30 @@ vqdmull.s32 q8, d17, d16 @ CHECK: ldmia r2, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x92,0xe8] +@ CHECK: ldmia r2, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x92,0xe8] @ CHECK: ldmib r2, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x92,0xe9] @ CHECK: ldmda r2, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x12,0xe8] @ CHECK: ldmdb r2, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x12,0xe9] +@ CHECK: ldmia r2, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x92,0xe8] + ldm r2, {r1,r3-r6,sp} ldmia r2, {r1,r3-r6,sp} ldmib r2, {r1,r3-r6,sp} ldmda r2, {r1,r3-r6,sp} ldmdb r2, {r1,r3-r6,sp} + ldmfd r2, {r1,r3-r6,sp} @ CHECK: stmia r2, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x82,0xe8] +@ CHECK: stmia r2, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x82,0xe8] @ CHECK: stmib r2, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x82,0xe9] @ CHECK: stmda r2, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x02,0xe8] @ CHECK: stmdb r2, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x02,0xe9] +@ CHECK: stmdb r2, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x02,0xe9] + stm r2, {r1,r3-r6,sp} stmia r2, {r1,r3-r6,sp} stmib r2, {r1,r3-r6,sp} stmda r2, {r1,r3-r6,sp} stmdb r2, {r1,r3-r6,sp} + stmfd r2, {r1,r3-r6,sp} @ CHECK: ldmia r2!, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0xb2,0xe8] @ CHECK: ldmib r2!, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0xb2,0xe9] -- cgit v1.1 From 660a9ec4aa08b42a1379e5caa3935d301b1e27b7 Mon Sep 17 00:00:00 2001 From: Jim Grosbach Date: Mon, 27 Jun 2011 20:40:29 +0000 Subject: ARM assembly carry set/clear condition code aliases for 'hi/lo' git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133938 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 4bc12c9..7e37d8d 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -1769,7 +1769,9 @@ static StringRef SplitMnemonic(StringRef Mnemonic, .Case("eq", ARMCC::EQ) .Case("ne", ARMCC::NE) .Case("hs", ARMCC::HS) + .Case("cs", ARMCC::HS) .Case("lo", ARMCC::LO) + .Case("cc", ARMCC::LO) .Case("mi", ARMCC::MI) .Case("pl", ARMCC::PL) .Case("vs", ARMCC::VS) -- cgit v1.1 From d1f0bbee189ea7cd18d03c4f9f55d0a33b070814 Mon Sep 17 00:00:00 2001 From: Jim Grosbach Date: Mon, 27 Jun 2011 20:59:10 +0000 Subject: Add exception necessitated by 133938. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133939 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 7e37d8d..48daad0 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -1761,7 +1761,7 @@ static StringRef SplitMnemonic(StringRef Mnemonic, Mnemonic == "vcle" || (Mnemonic == "smlal" || Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" || Mnemonic == "vmlal" || Mnemonic == "vpadal" || - Mnemonic == "vqdmlal")) + Mnemonic == "vqdmlal" || Mnemonic == "bics")) return Mnemonic; // First, split out any predication code. -- cgit v1.1 From bea6f615eefae279e53bbb63a31d2c3c67274c45 Mon Sep 17 00:00:00 2001 From: Owen Anderson Date: Mon, 27 Jun 2011 21:06:21 +0000 Subject: Add support for alternative register names, useful for instructions whose operands are logically equivalent to existing registers, but happen to be printed specially. For example, an instruciton that prints d0[0] instead of s0. Patch by Jim Grosbach. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133940 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Target/Target.td | 39 +++++++++- utils/TableGen/AsmMatcherEmitter.cpp | 25 +++++++ utils/TableGen/AsmWriterEmitter.cpp | 116 +++++++++++++++++++++++------- utils/TableGen/CodeGenDAGPatterns.cpp | 27 ++++++- utils/TableGen/CodeGenInstruction.cpp | 7 +- utils/TableGen/CodeGenTarget.cpp | 5 ++ utils/TableGen/CodeGenTarget.h | 7 ++ utils/TableGen/DAGISelMatcherGen.cpp | 18 +++-- utils/TableGen/FastISelEmitter.cpp | 4 ++ utils/TableGen/FixedLenDecoderEmitter.cpp | 4 +- utils/TableGen/InstrInfoEmitter.cpp | 34 ++++----- utils/TableGen/Record.cpp | 19 +++++ utils/TableGen/Record.h | 6 ++ utils/TableGen/RegisterInfoEmitter.cpp | 12 ++++ 14 files changed, 268 insertions(+), 55 deletions(-) diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td index bc8be89..4d7116b 100644 --- a/include/llvm/Target/Target.td +++ b/include/llvm/Target/Target.td @@ -26,11 +26,19 @@ class SubRegIndex { string Namespace = ""; } +// RegAltNameIndex - The alternate name set to use for register operands of +// this register class when printing. +class RegAltNameIndex { + string Namespace = ""; +} +def NoRegAltName : RegAltNameIndex; + // Register - You should define one instance of this class for each register // in the target machine. String n will become the "name" of the register. -class Register { +class Register altNames = []> { string Namespace = ""; string AsmName = n; + list AltNames = altNames; // Aliases - A list of registers that this register overlaps with. A read or // modification of this register can potentially read or modify the aliased @@ -48,6 +56,10 @@ class Register { // SubRegs. list SubRegIndices = []; + // RegAltNameIndices - The alternate name indices which are valid for this + // register. + list RegAltNameIndices = []; + // CompositeIndices - Specify subreg indices that don't correspond directly to // a register in SubRegs and are not inherited. The following formats are // supported: @@ -92,7 +104,7 @@ class RegisterWithSubRegs subregs> : Register { // registers by register allocators. // class RegisterClass regTypes, int alignment, - dag regList> { + dag regList, RegAltNameIndex idx = NoRegAltName> { string Namespace = namespace; // RegType - Specify the list ValueType of the registers in this register @@ -124,6 +136,11 @@ class RegisterClass regTypes, int alignment, // dag MemberList = regList; + // AltNameIndex - The alternate register name to use when printing operands + // of this register class. Every register in the register class must have + // a valid alternate name for the given index. + RegAltNameIndex altNameIndex = idx; + // SubRegClasses - Specify the register class of subregisters as a list of // dags: (RegClass SubRegIndex, SubRegindex, ...) list SubRegClasses = []; @@ -466,6 +483,24 @@ class Operand { AsmOperandClass ParserMatchClass = ImmAsmOperand; } +class RegisterOperand { + // RegClass - The register class of the operand. + RegisterClass RegClass = regclass; + // PrintMethod - The target method to call to print register operands of + // this type. The method normally will just use an alt-name index to look + // up the name to print. Default to the generic printOperand(). + string PrintMethod = pm; + // ParserMatchClass - The "match class" that operands of this type fit + // in. Match classes are used to define the order in which instructions are + // match, to ensure that which instructions gets matched is deterministic. + // + // The target specific parser must be able to classify an parsed operand into + // a unique class, which does not partially overlap with any other classes. It + // can match a subset of some other class, in which case the AsmOperandClass + // should declare the other operand as one of its super classes. + AsmOperandClass ParserMatchClass; +} + def i1imm : Operand; def i8imm : Operand; def i16imm : Operand; diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp index a05867b..1fb92ee 100644 --- a/utils/TableGen/AsmMatcherEmitter.cpp +++ b/utils/TableGen/AsmMatcherEmitter.cpp @@ -871,6 +871,31 @@ AsmMatcherInfo::getOperandClass(const CGIOperandList::OperandInfo &OI, if (SubOpIdx != -1) Rec = dynamic_cast(OI.MIOperandInfo->getArg(SubOpIdx))->getDef(); + if (Rec->isSubClassOf("RegisterOperand")) { + // RegisterOperand may have an associated ParserMatchClass. If it does, + // use it, else just fall back to the underlying register class. + const RecordVal *R = Rec->getValue("ParserMatchClass"); + if (R == 0 || R->getValue() == 0) + throw "Record `" + Rec->getName() + + "' does not have a ParserMatchClass!\n"; + + if (DefInit *DI= dynamic_cast(R->getValue())) { + Record *MatchClass = DI->getDef(); + if (ClassInfo *CI = AsmOperandClasses[MatchClass]) + return CI; + } + + // No custom match class. Just use the register class. + Record *ClassRec = Rec->getValueAsDef("RegClass"); + if (!ClassRec) + throw TGError(Rec->getLoc(), "RegisterOperand `" + Rec->getName() + + "' has no associated register class!\n"); + if (ClassInfo *CI = RegisterClassClasses[ClassRec]) + return CI; + throw TGError(Rec->getLoc(), "register class has no class info!"); + } + + if (Rec->isSubClassOf("RegisterClass")) { if (ClassInfo *CI = RegisterClassClasses[Rec]) return CI; diff --git a/utils/TableGen/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp index 066e03d..53df7dd 100644 --- a/utils/TableGen/AsmWriterEmitter.cpp +++ b/utils/TableGen/AsmWriterEmitter.cpp @@ -18,6 +18,7 @@ #include "CodeGenTarget.h" #include "Record.h" #include "StringToOffsetTable.h" +#include "llvm/ADT/Twine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/MathExtras.h" #include @@ -458,6 +459,58 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) { O << "}\n"; } +static void +emitRegisterNameString(raw_ostream &O, StringRef AltName, + const std::vector &Registers) { + StringToOffsetTable StringTable; + O << " static const unsigned RegAsmOffset" << AltName << "[] = {\n "; + for (unsigned i = 0, e = Registers.size(); i != e; ++i) { + const CodeGenRegister &Reg = *Registers[i]; + + StringRef AsmName; + // "NoRegAltName" is special. We don't need to do a lookup for that, + // as it's just a reference to the default register name. + if (AltName == "" || AltName == "NoRegAltName") { + AsmName = Reg.TheDef->getValueAsString("AsmName"); + if (AsmName.empty()) + AsmName = Reg.getName(); + } else { + // Make sure the register has an alternate name for this index. + std::vector AltNameList = + Reg.TheDef->getValueAsListOfDefs("RegAltNameIndices"); + unsigned Idx = 0, e; + for (e = AltNameList.size(); + Idx < e && (AltNameList[Idx]->getName() != AltName); + ++Idx) + ; + // If the register has an alternate name for this index, use it. + // Otherwise, leave it empty as an error flag. + if (Idx < e) { + std::vector AltNames = + Reg.TheDef->getValueAsListOfStrings("AltNames"); + if (AltNames.size() <= Idx) + throw TGError(Reg.TheDef->getLoc(), + (Twine("Register definition missing alt name for '") + + AltName + "'.").str()); + AsmName = AltNames[Idx]; + } + } + + O << StringTable.GetOrAddStringOffset(AsmName); + if (((i + 1) % 14) == 0) + O << ",\n "; + else + O << ", "; + + } + O << "0\n" + << " };\n" + << "\n"; + + O << " const char *AsmStrs" << AltName << " =\n"; + StringTable.EmitString(O); + O << ";\n"; +} void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) { CodeGenTarget Target(Records); @@ -465,40 +518,48 @@ void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) { std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName"); const std::vector &Registers = Target.getRegBank().getRegisters(); + std::vector AltNameIndices = Target.getRegAltNameIndices(); + bool hasAltNames = AltNameIndices.size() > 1; - StringToOffsetTable StringTable; O << "\n\n/// getRegisterName - This method is automatically generated by tblgen\n" "/// from the register set description. This returns the assembler name\n" "/// for the specified register.\n" - "const char *" << Target.getName() << ClassName - << "::getRegisterName(unsigned RegNo) {\n" - << " assert(RegNo && RegNo < " << (Registers.size()+1) - << " && \"Invalid register number!\");\n" - << "\n" - << " static const unsigned RegAsmOffset[] = {"; - for (unsigned i = 0, e = Registers.size(); i != e; ++i) { - const CodeGenRegister &Reg = *Registers[i]; - - std::string AsmName = Reg.TheDef->getValueAsString("AsmName"); - if (AsmName.empty()) - AsmName = Reg.getName(); - - - if ((i % 14) == 0) - O << "\n "; - - O << StringTable.GetOrAddStringOffset(AsmName) << ", "; - } - O << "0\n" - << " };\n" + "const char *" << Target.getName() << ClassName << "::"; + if (hasAltNames) + O << "\ngetRegisterName(unsigned RegNo, unsigned AltIdx) {\n"; + else + O << "getRegisterName(unsigned RegNo) {\n"; + O << " assert(RegNo && RegNo < " << (Registers.size()+1) + << " && \"Invalid register number!\");\n" << "\n"; - O << " const char *AsmStrs =\n"; - StringTable.EmitString(O); - O << ";\n"; + if (hasAltNames) { + for (unsigned i = 0, e = AltNameIndices.size(); i < e; ++i) + emitRegisterNameString(O, AltNameIndices[i]->getName(), Registers); + } else + emitRegisterNameString(O, "", Registers); + + if (hasAltNames) { + O << " const unsigned *RegAsmOffset;\n" + << " const char *AsmStrs;\n" + << " switch(AltIdx) {\n" + << " default: assert(0 && \"Invalid register alt name index!\");\n"; + for (unsigned i = 0, e = AltNameIndices.size(); i < e; ++i) { + StringRef Namespace = AltNameIndices[1]->getValueAsString("Namespace"); + StringRef AltName(AltNameIndices[i]->getName()); + O << " case " << Namespace << "::" << AltName + << ":\n" + << " AsmStrs = AsmStrs" << AltName << ";\n" + << " RegAsmOffset = RegAsmOffset" << AltName << ";\n" + << " break;\n"; + } + O << "}\n"; + } - O << " return AsmStrs+RegAsmOffset[RegNo-1];\n" + O << " assert (*(AsmStrs+RegAsmOffset[RegNo-1]) &&\n" + << " \"Invalid alt name index for register!\");\n" + << " return AsmStrs+RegAsmOffset[RegNo-1];\n" << "}\n"; } @@ -936,6 +997,9 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { const Record *Rec = RO.getRecord(); StringRef ROName = RO.getName(); + + if (Rec->isSubClassOf("RegisterOperand")) + Rec = Rec->getValueAsDef("RegClass"); if (Rec->isSubClassOf("RegisterClass")) { Cond = std::string("MI->getOperand(")+llvm::utostr(i)+").isReg()"; IAP->addCond(Cond); diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp index 1930a96..0fe5d05 100644 --- a/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/utils/TableGen/CodeGenDAGPatterns.cpp @@ -1242,6 +1242,16 @@ TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) { /// static EEVT::TypeSet getImplicitType(Record *R, unsigned ResNo, bool NotRegisters, TreePattern &TP) { + // Check to see if this is a register operand. + if (R->isSubClassOf("RegisterOperand")) { + assert(ResNo == 0 && "Regoperand ref only has one result!"); + if (NotRegisters) + return EEVT::TypeSet(); // Unknown. + Record *RegClass = R->getValueAsDef("RegClass"); + const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo(); + return EEVT::TypeSet(T.getRegisterClass(RegClass).getValueTypes()); + } + // Check to see if this is a register or a register class. if (R->isSubClassOf("RegisterClass")) { assert(ResNo == 0 && "Regclass ref only has one result!"); @@ -1524,6 +1534,11 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { if (ResultNode->isSubClassOf("PointerLikeRegClass")) { MadeChange |= UpdateNodeType(ResNo, MVT::iPTR, TP); + } else if (ResultNode->isSubClassOf("RegisterOperand")) { + Record *RegClass = ResultNode->getValueAsDef("RegClass"); + const CodeGenRegisterClass &RC = + CDP.getTargetInfo().getRegisterClass(RegClass); + MadeChange |= UpdateNodeType(ResNo, RC.getValueTypes(), TP); } else if (ResultNode->getName() == "unknown") { // Nothing to do. } else { @@ -1582,6 +1597,11 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { const CodeGenRegisterClass &RC = CDP.getTargetInfo().getRegisterClass(OperandNode); MadeChange |= Child->UpdateNodeType(ChildResNo, RC.getValueTypes(), TP); + } else if (OperandNode->isSubClassOf("RegisterOperand")) { + Record *RegClass = OperandNode->getValueAsDef("RegClass"); + const CodeGenRegisterClass &RC = + CDP.getTargetInfo().getRegisterClass(RegClass); + MadeChange |= Child->UpdateNodeType(ChildResNo, RC.getValueTypes(), TP); } else if (OperandNode->isSubClassOf("Operand")) { VT = getValueType(OperandNode->getValueAsDef("Type")); MadeChange |= Child->UpdateNodeType(ChildResNo, VT, TP); @@ -1928,7 +1948,8 @@ InferAllTypes(const StringMap > *InNamedTypes) { // def : Pat<(v1i64 (bitconvert(v2i32 DPR:$src))), (v1i64 DPR:$src)>; if (Nodes[i] == Trees[0] && Nodes[i]->isLeaf()) { DefInit *DI = dynamic_cast(Nodes[i]->getLeafValue()); - if (DI && DI->getDef()->isSubClassOf("RegisterClass")) + if (DI && (DI->getDef()->isSubClassOf("RegisterClass") || + DI->getDef()->isSubClassOf("RegisterOperand"))) continue; } @@ -2211,7 +2232,8 @@ static bool HandleUse(TreePattern *I, TreePatternNode *Pat, if (Pat->getName().empty()) { if (Pat->isLeaf()) { DefInit *DI = dynamic_cast(Pat->getLeafValue()); - if (DI && DI->getDef()->isSubClassOf("RegisterClass")) + if (DI && (DI->getDef()->isSubClassOf("RegisterClass") || + DI->getDef()->isSubClassOf("RegisterOperand"))) I->error("Input " + DI->getDef()->getName() + " must be named!"); } return false; @@ -2318,6 +2340,7 @@ FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat, I->error("set destination should be a register!"); if (Val->getDef()->isSubClassOf("RegisterClass") || + Val->getDef()->isSubClassOf("RegisterOperand") || Val->getDef()->isSubClassOf("PointerLikeRegClass")) { if (Dest->getName().empty()) I->error("set destination must have a name!"); diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp index e9557d2..5fa91be 100644 --- a/utils/TableGen/CodeGenInstruction.cpp +++ b/utils/TableGen/CodeGenInstruction.cpp @@ -69,7 +69,9 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) { std::string EncoderMethod; unsigned NumOps = 1; DagInit *MIOpInfo = 0; - if (Rec->isSubClassOf("Operand")) { + if (Rec->isSubClassOf("RegisterOperand")) { + PrintMethod = Rec->getValueAsString("PrintMethod"); + } else if (Rec->isSubClassOf("Operand")) { PrintMethod = Rec->getValueAsString("PrintMethod"); // If there is an explicit encoder method, use it. EncoderMethod = Rec->getValueAsString("EncoderMethod"); @@ -415,6 +417,9 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo, // Handle explicit registers. if (ADI && ADI->getDef()->isSubClassOf("Register")) { + if (InstOpRec->isSubClassOf("RegisterOperand")) + InstOpRec = InstOpRec->getValueAsDef("RegClass"); + if (!InstOpRec->isSubClassOf("RegisterClass")) return false; diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp index 5b0b315..929791c 100644 --- a/utils/TableGen/CodeGenTarget.cpp +++ b/utils/TableGen/CodeGenTarget.cpp @@ -164,6 +164,11 @@ CodeGenRegBank &CodeGenTarget::getRegBank() const { return *RegBank; } +void CodeGenTarget::ReadRegAltNameIndices() const { + RegAltNameIndices = Records.getAllDerivedDefinitions("RegAltNameIndex"); + std::sort(RegAltNameIndices.begin(), RegAltNameIndices.end(), LessRecord()); +} + /// getRegisterByName - If there is a register with the specific AsmName, /// return it. const CodeGenRegister *CodeGenTarget::getRegisterByName(StringRef Name) const { diff --git a/utils/TableGen/CodeGenTarget.h b/utils/TableGen/CodeGenTarget.h index 9bedb9c..143daed 100644 --- a/utils/TableGen/CodeGenTarget.h +++ b/utils/TableGen/CodeGenTarget.h @@ -66,7 +66,9 @@ class CodeGenTarget { mutable DenseMap Instructions; mutable CodeGenRegBank *RegBank; + mutable std::vector RegAltNameIndices; mutable std::vector LegalValueTypes; + void ReadRegAltNameIndices() const; void ReadInstructions() const; void ReadLegalValueTypes() const; @@ -100,6 +102,11 @@ public: /// return it. const CodeGenRegister *getRegisterByName(StringRef Name) const; + const std::vector &getRegAltNameIndices() const { + if (RegAltNameIndices.empty()) ReadRegAltNameIndices(); + return RegAltNameIndices; + } + const std::vector &getRegisterClasses() const { return getRegBank().getRegClasses(); } diff --git a/utils/TableGen/DAGISelMatcherGen.cpp b/utils/TableGen/DAGISelMatcherGen.cpp index 54553a8..c5897c7 100644 --- a/utils/TableGen/DAGISelMatcherGen.cpp +++ b/utils/TableGen/DAGISelMatcherGen.cpp @@ -224,6 +224,7 @@ void MatcherGen::EmitLeafMatchCode(const TreePatternNode *N) { Record *LeafRec = DI->getDef(); if (// Handle register references. Nothing to do here, they always match. LeafRec->isSubClassOf("RegisterClass") || + LeafRec->isSubClassOf("RegisterOperand") || LeafRec->isSubClassOf("PointerLikeRegClass") || LeafRec->isSubClassOf("SubRegIndex") || // Place holder for SRCVALUE nodes. Nothing to do here. @@ -579,15 +580,16 @@ void MatcherGen::EmitResultLeafAsOperand(const TreePatternNode *N, // If this is an explicit register reference, handle it. if (DefInit *DI = dynamic_cast(N->getLeafValue())) { - if (DI->getDef()->isSubClassOf("Register")) { + Record *Def = DI->getDef(); + if (Def->isSubClassOf("Register")) { const CodeGenRegister *Reg = - CGP.getTargetInfo().getRegBank().getReg(DI->getDef()); + CGP.getTargetInfo().getRegBank().getReg(Def); AddMatcher(new EmitRegisterMatcher(Reg, N->getType(0))); ResultOps.push_back(NextRecordedOperandNo++); return; } - if (DI->getDef()->getName() == "zero_reg") { + if (Def->getName() == "zero_reg") { AddMatcher(new EmitRegisterMatcher(0, N->getType(0))); ResultOps.push_back(NextRecordedOperandNo++); return; @@ -595,16 +597,18 @@ void MatcherGen::EmitResultLeafAsOperand(const TreePatternNode *N, // Handle a reference to a register class. This is used // in COPY_TO_SUBREG instructions. - if (DI->getDef()->isSubClassOf("RegisterClass")) { - std::string Value = getQualifiedName(DI->getDef()) + "RegClassID"; + if (Def->isSubClassOf("RegisterOperand")) + Def = Def->getValueAsDef("RegClass"); + if (Def->isSubClassOf("RegisterClass")) { + std::string Value = getQualifiedName(Def) + "RegClassID"; AddMatcher(new EmitStringIntegerMatcher(Value, MVT::i32)); ResultOps.push_back(NextRecordedOperandNo++); return; } // Handle a subregister index. This is used for INSERT_SUBREG etc. - if (DI->getDef()->isSubClassOf("SubRegIndex")) { - std::string Value = getQualifiedName(DI->getDef()); + if (Def->isSubClassOf("SubRegIndex")) { + std::string Value = getQualifiedName(Def); AddMatcher(new EmitStringIntegerMatcher(Value, MVT::i32)); ResultOps.push_back(NextRecordedOperandNo++); return; diff --git a/utils/TableGen/FastISelEmitter.cpp b/utils/TableGen/FastISelEmitter.cpp index f946ac7..f54e8df 100644 --- a/utils/TableGen/FastISelEmitter.cpp +++ b/utils/TableGen/FastISelEmitter.cpp @@ -248,6 +248,8 @@ struct OperandsSignature { // For now, the only other thing we accept is register operands. const CodeGenRegisterClass *RC = 0; + if (OpLeafRec->isSubClassOf("RegisterOperand")) + OpLeafRec = OpLeafRec->getValueAsDef("RegClass"); if (OpLeafRec->isSubClassOf("RegisterClass")) RC = &Target.getRegisterClass(OpLeafRec); else if (OpLeafRec->isSubClassOf("Register")) @@ -454,6 +456,8 @@ void FastISelMap::collectPatterns(CodeGenDAGPatterns &CGP) { std::string SubRegNo; if (Op->getName() != "EXTRACT_SUBREG") { Record *Op0Rec = II.Operands[0].Rec; + if (Op0Rec->isSubClassOf("RegisterOperand")) + Op0Rec = Op0Rec->getValueAsDef("RegClass"); if (!Op0Rec->isSubClassOf("RegisterClass")) continue; DstRC = &Target.getRegisterClass(Op0Rec); diff --git a/utils/TableGen/FixedLenDecoderEmitter.cpp b/utils/TableGen/FixedLenDecoderEmitter.cpp index 9312fe8..ba6cd86 100644 --- a/utils/TableGen/FixedLenDecoderEmitter.cpp +++ b/utils/TableGen/FixedLenDecoderEmitter.cpp @@ -1305,8 +1305,10 @@ bool FixedLenDecoderEmitter::populateInstruction(const CodeGenInstruction &CGI, RecordRecTy *Type = dynamic_cast(TI->getType()); Record *TypeRecord = Type->getRecord(); bool isReg = false; + if (TypeRecord->isSubClassOf("RegisterOperand")) + TypeRecord = TypeRecord->getValueAsDef("RegClass"); if (TypeRecord->isSubClassOf("RegisterClass")) { - Decoder = "Decode" + Type->getRecord()->getName() + "RegisterClass"; + Decoder = "Decode" + TypeRecord->getName() + "RegisterClass"; isReg = true; } diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp index fc544ee..6a96696 100644 --- a/utils/TableGen/InstrInfoEmitter.cpp +++ b/utils/TableGen/InstrInfoEmitter.cpp @@ -43,10 +43,10 @@ void InstrInfoEmitter::GatherItinClasses() { std::vector DefList = Records.getAllDerivedDefinitions("InstrItinClass"); std::sort(DefList.begin(), DefList.end(), LessRecord()); - + for (unsigned i = 0, N = DefList.size(); i < N; i++) ItinClassMap[DefList[i]->getName()] = i; -} +} unsigned InstrInfoEmitter::getItinClassNumber(const Record *InstRec) { return ItinClassMap[InstRec->getValueAsDef("Itinerary")->getName()]; @@ -59,7 +59,7 @@ unsigned InstrInfoEmitter::getItinClassNumber(const Record *InstRec) { std::vector InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) { std::vector Result; - + for (unsigned i = 0, e = Inst.Operands.size(); i != e; ++i) { // Handle aggregate operands and normal operands the same way by expanding // either case into a list of operands for this op. @@ -70,7 +70,7 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) { // operand, which has a single operand, but no declared class for the // operand. DagInit *MIOI = Inst.Operands[i].MIOperandInfo; - + if (!MIOI || MIOI->getNumArgs() == 0) { // Single, anonymous, operand. OperandList.push_back(Inst.Operands[i]); @@ -86,7 +86,9 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) { for (unsigned j = 0, e = OperandList.size(); j != e; ++j) { Record *OpR = OperandList[j].Rec; std::string Res; - + + if (OpR->isSubClassOf("RegisterOperand")) + OpR = OpR->getValueAsDef("RegClass"); if (OpR->isSubClassOf("RegisterClass")) Res += getQualifiedName(OpR) + "RegClassID, "; else if (OpR->isSubClassOf("PointerLikeRegClass")) @@ -94,10 +96,10 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) { else // -1 means the operand does not have a fixed register class. Res += "-1, "; - + // Fill in applicable flags. Res += "0"; - + // Ptr value whose register class is resolved via callback. if (OpR->isSubClassOf("PointerLikeRegClass")) Res += "|(1<isSubClassOf("PredicateOperand")) Res += "|(1<isSubClassOf("OptionalDefOperand")) @@ -114,7 +116,7 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) { // Fill in constraint info. Res += ", "; - + const CGIOperandList::ConstraintInfo &Constraint = Inst.Operands[i].Constraints[j]; if (Constraint.isNone()) @@ -126,7 +128,7 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) { Res += "((" + utostr(Constraint.getTiedOperand()) + " << 16) | (1 << TOI::TIED_TO))"; } - + Result.push_back(Res); } } @@ -134,12 +136,12 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) { return Result; } -void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS, +void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS, OperandInfoMapTy &OperandInfoIDs) { // ID #0 is for no operand info. unsigned OperandListNum = 0; OperandInfoIDs[std::vector()] = ++OperandListNum; - + OS << "\n"; const CodeGenTarget &Target = CDP.getTargetInfo(); for (CodeGenTarget::inst_iterator II = Target.inst_begin(), @@ -147,7 +149,7 @@ void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS, std::vector OperandInfo = GetOperandInfo(**II); unsigned &N = OperandInfoIDs[OperandInfo]; if (N != 0) continue; - + N = ++OperandListNum; OS << "static const TargetOperandInfo OperandInfo" << N << "[] = { "; for (unsigned i = 0, e = OperandInfo.size(); i != e; ++i) @@ -205,7 +207,7 @@ void InstrInfoEmitter::run(raw_ostream &OS) { std::map, unsigned> EmittedBarriers; unsigned BarrierNumber = 0; std::map BarriersMap; - + // Emit all of the instruction's implicit uses and defs. for (CodeGenTarget::inst_iterator II = Target.inst_begin(), E = Target.inst_end(); II != E; ++II) { @@ -231,10 +233,10 @@ void InstrInfoEmitter::run(raw_ostream &OS) { } OperandInfoMapTy OperandInfoIDs; - + // Emit all of the operand info records. EmitOperandInfo(OS, OperandInfoIDs); - + // Emit all of the TargetInstrDesc records in their ENUM ordering. // OS << "\nstatic const TargetInstrDesc " << TargetName diff --git a/utils/TableGen/Record.cpp b/utils/TableGen/Record.cpp index 3c750da..730eca1 100644 --- a/utils/TableGen/Record.cpp +++ b/utils/TableGen/Record.cpp @@ -1443,6 +1443,25 @@ Record::getValueAsListOfInts(StringRef FieldName) const { return Ints; } +/// getValueAsListOfStrings - This method looks up the specified field and +/// returns its value as a vector of strings, throwing an exception if the +/// field does not exist or if the value is not the right type. +/// +std::vector +Record::getValueAsListOfStrings(StringRef FieldName) const { + ListInit *List = getValueAsListInit(FieldName); + std::vector Strings; + for (unsigned i = 0; i < List->getSize(); i++) { + if (StringInit *II = dynamic_cast(List->getElement(i))) { + Strings.push_back(II->getValue()); + } else { + throw "Record `" + getName() + "', field `" + FieldName.str() + + "' does not have a list of strings initializer!"; + } + } + return Strings; +} + /// getValueAsDef - This method looks up the specified field and returns its /// value as a Record, throwing an exception if the field does not exist or if /// the value is not the right type. diff --git a/utils/TableGen/Record.h b/utils/TableGen/Record.h index c8905cc..f24f5e6 100644 --- a/utils/TableGen/Record.h +++ b/utils/TableGen/Record.h @@ -1368,6 +1368,12 @@ public: /// std::vector getValueAsListOfInts(StringRef FieldName) const; + /// getValueAsListOfStrings - This method looks up the specified field and + /// returns its value as a vector of strings, throwing an exception if the + /// field does not exist or if the value is not the right type. + /// + std::vector getValueAsListOfStrings(StringRef FieldName) const; + /// getValueAsDef - This method looks up the specified field and returns its /// value as a Record, throwing an exception if the field does not exist or if /// the value is not the right type. diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp index ab081eb..f8ce3ac 100644 --- a/utils/TableGen/RegisterInfoEmitter.cpp +++ b/utils/TableGen/RegisterInfoEmitter.cpp @@ -112,6 +112,18 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, OS << "0 };\n"; } + const std::vector RegAltNameIndices = Target.getRegAltNameIndices(); + // If the only definition is the default NoRegAltName, we don't need to + // emit anything. + if (RegAltNameIndices.size() > 1) { + OS << "\n// Register alternate name indices\n"; + OS << "enum {\n"; + for (unsigned i = 0, e = RegAltNameIndices.size(); i != e; ++i) + OS << " " << RegAltNameIndices[i]->getName() << ",\t// " << i << "\n"; + OS << " NUM_TARGET_REG_ALT_NAMES = " << RegAltNameIndices.size() << "\n"; + OS << "};\n"; + } + // Emit the empty sub-registers list OS << " const unsigned Empty_SubRegsSet[] = { 0 };\n"; // Loop over all of the registers which have sub-registers, emitting the -- cgit v1.1 From 15993f83a419950f06d2879d6701530ae6449317 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Mon, 27 Jun 2011 21:26:13 +0000 Subject: More refactoring. Move getRegClass from TargetOperandInfo to TargetInstrInfo. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133944 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Target/TargetInstrDesc.h | 15 ----------- include/llvm/Target/TargetInstrInfo.h | 6 +++++ lib/CodeGen/AggressiveAntiDepBreaker.cpp | 4 +-- lib/CodeGen/CalcSpillWeights.cpp | 3 ++- lib/CodeGen/CriticalAntiDepBreaker.cpp | 4 +-- lib/CodeGen/MachineLICM.cpp | 2 +- lib/CodeGen/MachineVerifier.cpp | 8 +++--- lib/CodeGen/RegisterCoalescer.cpp | 4 +-- lib/CodeGen/SelectionDAG/InstrEmitter.cpp | 6 ++--- lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp | 2 +- lib/CodeGen/StackSlotColoring.cpp | 4 +-- lib/CodeGen/TwoAddressInstructionPass.cpp | 2 +- lib/Target/ARM/ARMBaseRegisterInfo.cpp | 2 +- lib/Target/ARM/ARMLoadStoreOptimizer.cpp | 2 +- lib/Target/ARM/MLxExpansionPass.cpp | 2 +- lib/Target/Blackfin/BlackfinISelDAGToDAG.cpp | 4 +-- lib/Target/TargetInstrInfo.cpp | 36 +++++++++++++------------- lib/Target/X86/X86InstrInfo.cpp | 11 ++++---- 18 files changed, 54 insertions(+), 63 deletions(-) diff --git a/include/llvm/Target/TargetInstrDesc.h b/include/llvm/Target/TargetInstrDesc.h index 6e20e8a..ecd2acc 100644 --- a/include/llvm/Target/TargetInstrDesc.h +++ b/include/llvm/Target/TargetInstrDesc.h @@ -52,9 +52,6 @@ public: /// if the operand is a register. If isLookupPtrRegClass is set, then this is /// an index that is passed to TargetRegisterInfo::getPointerRegClass(x) to /// get a dynamic register class. - /// - /// NOTE: This member should be considered to be private, all access should go - /// through "getRegClass(TRI)" below. short RegClass; /// Flags - These are flags from the TOI::OperandFlags enum. @@ -65,12 +62,6 @@ public: unsigned Constraints; /// Currently no other information. - /// getRegClass - Get the register class for the operand, handling resolution - /// of "symbolic" pointer register classes etc. If this is not a register - /// operand, this returns null. - const TargetRegisterClass *getRegClass(const TargetRegisterInfo *TRI) const; - - /// isLookupPtrRegClass - Set if this operand is a pointer value and it /// requires a callback to look up its register class. bool isLookupPtrRegClass() const { return Flags&(1 <getDesc().getNumOperands()) - RC = MI->getDesc().OpInfo[i].getRegClass(TRI); + RC = TII->getRegClass(MI->getDesc(), i, TRI); AggressiveAntiDepState::RegisterReference RR = { &MO, RC }; RegRefs.insert(std::make_pair(Reg, RR)); } @@ -479,7 +479,7 @@ void AggressiveAntiDepBreaker::ScanInstruction(MachineInstr *MI, // Note register reference... const TargetRegisterClass *RC = NULL; if (i < MI->getDesc().getNumOperands()) - RC = MI->getDesc().OpInfo[i].getRegClass(TRI); + RC = TII->getRegClass(MI->getDesc(), i, TRI); AggressiveAntiDepState::RegisterReference RR = { &MO, RC }; RegRefs.insert(std::make_pair(Reg, RR)); } diff --git a/lib/CodeGen/CalcSpillWeights.cpp b/lib/CodeGen/CalcSpillWeights.cpp index 5d722ee..74c43cc 100644 --- a/lib/CodeGen/CalcSpillWeights.cpp +++ b/lib/CodeGen/CalcSpillWeights.cpp @@ -188,6 +188,7 @@ void VirtRegAuxInfo::CalculateWeightAndHint(LiveInterval &li) { void VirtRegAuxInfo::CalculateRegClass(unsigned reg) { MachineRegisterInfo &MRI = MF.getRegInfo(); + const TargetInstrInfo *TII = MF.getTarget().getInstrInfo(); const TargetRegisterInfo *TRI = MF.getTarget().getRegisterInfo(); const TargetRegisterClass *OldRC = MRI.getRegClass(reg); const TargetRegisterClass *NewRC = TRI->getLargestLegalSuperClass(OldRC); @@ -203,7 +204,7 @@ void VirtRegAuxInfo::CalculateRegClass(unsigned reg) { if (I.getOperand().getSubReg()) return; const TargetRegisterClass *OpRC = - I->getDesc().getRegClass(I.getOperandNo(), TRI); + TII->getRegClass(I->getDesc(), I.getOperandNo(), TRI); if (OpRC) NewRC = getCommonSubClass(NewRC, OpRC); if (!NewRC || NewRC == OldRC) diff --git a/lib/CodeGen/CriticalAntiDepBreaker.cpp b/lib/CodeGen/CriticalAntiDepBreaker.cpp index 4cac453..84c4d59 100644 --- a/lib/CodeGen/CriticalAntiDepBreaker.cpp +++ b/lib/CodeGen/CriticalAntiDepBreaker.cpp @@ -207,7 +207,7 @@ void CriticalAntiDepBreaker::PrescanInstruction(MachineInstr *MI) { const TargetRegisterClass *NewRC = 0; if (i < MI->getDesc().getNumOperands()) - NewRC = MI->getDesc().OpInfo[i].getRegClass(TRI); + NewRC = TII->getRegClass(MI->getDesc(), i, TRI); // For now, only allow the register to be changed if its register // class is consistent across all uses. @@ -295,7 +295,7 @@ void CriticalAntiDepBreaker::ScanInstruction(MachineInstr *MI, const TargetRegisterClass *NewRC = 0; if (i < MI->getDesc().getNumOperands()) - NewRC = MI->getDesc().OpInfo[i].getRegClass(TRI); + NewRC = TII->getRegClass(MI->getDesc(), i, TRI); // For now, only allow the register to be changed if its register // class is consistent across all uses. diff --git a/lib/CodeGen/MachineLICM.cpp b/lib/CodeGen/MachineLICM.cpp index b315702..cfd0325 100644 --- a/lib/CodeGen/MachineLICM.cpp +++ b/lib/CodeGen/MachineLICM.cpp @@ -1020,7 +1020,7 @@ MachineInstr *MachineLICM::ExtractHoistableLoad(MachineInstr *MI) { if (NewOpc == 0) return 0; const TargetInstrDesc &TID = TII->get(NewOpc); if (TID.getNumDefs() != 1) return 0; - const TargetRegisterClass *RC = TID.OpInfo[LoadRegIndex].getRegClass(TRI); + const TargetRegisterClass *RC = TII->getRegClass(TID, LoadRegIndex, TRI); // Ok, we're unfolding. Create a temporary register and do the unfold. unsigned Reg = MRI->createVirtualRegister(RC); diff --git a/lib/CodeGen/MachineVerifier.cpp b/lib/CodeGen/MachineVerifier.cpp index 471463b..d3f8b02 100644 --- a/lib/CodeGen/MachineVerifier.cpp +++ b/lib/CodeGen/MachineVerifier.cpp @@ -62,6 +62,7 @@ namespace { raw_ostream *OS; const MachineFunction *MF; const TargetMachine *TM; + const TargetInstrInfo *TII; const TargetRegisterInfo *TRI; const MachineRegisterInfo *MRI; @@ -255,6 +256,7 @@ bool MachineVerifier::runOnMachineFunction(MachineFunction &MF) { this->MF = &MF; TM = &MF.getTarget(); + TII = TM->getInstrInfo(); TRI = TM->getRegisterInfo(); MRI = &MF.getRegInfo(); @@ -387,8 +389,6 @@ static bool matchPair(MachineBasicBlock::const_succ_iterator i, void MachineVerifier::visitMachineBasicBlockBefore(const MachineBasicBlock *MBB) { - const TargetInstrInfo *TII = MF->getTarget().getInstrInfo(); - // Count the number of landing pad successors. SmallPtrSet LandingPadSuccs; for (MachineBasicBlock::const_succ_iterator I = MBB->succ_begin(), @@ -723,7 +723,7 @@ MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) { } sr = s; } - if (const TargetRegisterClass *DRC = TOI.getRegClass(TRI)) { + if (const TargetRegisterClass *DRC = TII->getRegClass(TI, MONum, TRI)) { if (!DRC->contains(sr)) { report("Illegal physical register for instruction", MO, MONum); *OS << TRI->getName(sr) << " is not a " @@ -743,7 +743,7 @@ MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) { } RC = SRC; } - if (const TargetRegisterClass *DRC = TOI.getRegClass(TRI)) { + if (const TargetRegisterClass *DRC = TII->getRegClass(TI, MONum, TRI)) { if (!RC->hasSuperClassEq(DRC)) { report("Illegal virtual register for instruction", MO, MONum); *OS << "Expected a " << DRC->getName() << " register, but got a " diff --git a/lib/CodeGen/RegisterCoalescer.cpp b/lib/CodeGen/RegisterCoalescer.cpp index 06a26a7..d59843f 100644 --- a/lib/CodeGen/RegisterCoalescer.cpp +++ b/lib/CodeGen/RegisterCoalescer.cpp @@ -701,7 +701,7 @@ bool RegisterCoalescer::ReMaterializeTrivialDef(LiveInterval &SrcInt, // Make sure the copy destination register class fits the instruction // definition register class. The mismatch can happen as a result of earlier // extract_subreg, insert_subreg, subreg_to_reg coalescing. - const TargetRegisterClass *RC = TID.OpInfo[0].getRegClass(tri_); + const TargetRegisterClass *RC = tii_->getRegClass(TID, 0, tri_); if (TargetRegisterInfo::isVirtualRegister(DstReg)) { if (mri_->getRegClass(DstReg) != RC) return false; @@ -718,7 +718,7 @@ bool RegisterCoalescer::ReMaterializeTrivialDef(LiveInterval &SrcInt, const TargetRegisterClass *DstRC = mri_->getRegClass(DstReg); const TargetRegisterClass *DstSubRC = DstRC->getSubRegisterRegClass(DstSubIdx); - const TargetRegisterClass *DefRC = TID.OpInfo[0].getRegClass(tri_); + const TargetRegisterClass *DefRC = tii_->getRegClass(TID, 0, tri_); if (DefRC == DstRC) DstSubIdx = 0; else if (DefRC != DstSubRC) diff --git a/lib/CodeGen/SelectionDAG/InstrEmitter.cpp b/lib/CodeGen/SelectionDAG/InstrEmitter.cpp index e8c9c51..1759255 100644 --- a/lib/CodeGen/SelectionDAG/InstrEmitter.cpp +++ b/lib/CodeGen/SelectionDAG/InstrEmitter.cpp @@ -109,7 +109,7 @@ EmitCopyFromReg(SDNode *Node, unsigned ResNo, bool IsClone, bool IsCloned, const TargetInstrDesc &II = TII->get(User->getMachineOpcode()); const TargetRegisterClass *RC = 0; if (i+II.getNumDefs() < II.getNumOperands()) - RC = II.OpInfo[i+II.getNumDefs()].getRegClass(TRI); + RC = TII->getRegClass(II, i+II.getNumDefs(), TRI); if (!UseRC) UseRC = RC; else if (RC) { @@ -189,7 +189,7 @@ void InstrEmitter::CreateVirtualRegisters(SDNode *Node, MachineInstr *MI, // is a vreg in the same register class, use the CopyToReg'd destination // register instead of creating a new vreg. unsigned VRBase = 0; - const TargetRegisterClass *RC = II.OpInfo[i].getRegClass(TRI); + const TargetRegisterClass *RC = TII->getRegClass(II, i, TRI); if (II.OpInfo[i].isOptionalDef()) { // Optional def must be a physical register. unsigned NumResults = CountResults(Node); @@ -285,7 +285,7 @@ InstrEmitter::AddRegisterOperand(MachineInstr *MI, SDValue Op, const TargetRegisterClass *SrcRC = MRI->getRegClass(VReg); const TargetRegisterClass *DstRC = 0; if (IIOpNum < II->getNumOperands()) - DstRC = II->OpInfo[IIOpNum].getRegClass(TRI); + DstRC = TII->getRegClass(*II, IIOpNum, TRI); assert((DstRC || (TID.isVariadic() && IIOpNum >= TID.getNumOperands())) && "Don't have operand info for this instruction!"); if (DstRC && !SrcRC->hasSuperClassEq(DstRC)) { diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp index 091f3bc..ff36e75 100644 --- a/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp +++ b/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp @@ -303,7 +303,7 @@ static void GetCostForDef(const ScheduleDAGSDNodes::RegDefIter &RegDefPos, unsigned Idx = RegDefPos.GetIdx(); const TargetInstrDesc Desc = TII->get(Opcode); - const TargetRegisterClass *RC = Desc.getRegClass(Idx, TRI); + const TargetRegisterClass *RC = TII->getRegClass(Desc, Idx, TRI); RegClass = RC->getID(); // FIXME: Cost arbitrarily set to 1 because there doesn't seem to be a // better way to determine it. diff --git a/lib/CodeGen/StackSlotColoring.cpp b/lib/CodeGen/StackSlotColoring.cpp index 01f5b56..aefaa10 100644 --- a/lib/CodeGen/StackSlotColoring.cpp +++ b/lib/CodeGen/StackSlotColoring.cpp @@ -521,7 +521,7 @@ bool StackSlotColoring::PropagateBackward(MachineBasicBlock::iterator MII, if (MO.getSubReg() || MII->isSubregToReg()) return false; - const TargetRegisterClass *RC = TID.OpInfo[i].getRegClass(TRI); + const TargetRegisterClass *RC = TII->getRegClass(TID, i, TRI); if (RC && !RC->contains(NewReg)) return false; @@ -583,7 +583,7 @@ bool StackSlotColoring::PropagateForward(MachineBasicBlock::iterator MII, if (MO.getSubReg()) return false; - const TargetRegisterClass *RC = TID.OpInfo[i].getRegClass(TRI); + const TargetRegisterClass *RC = TII->getRegClass(TID, i, TRI); if (RC && !RC->contains(NewReg)) return false; if (MO.isKill()) diff --git a/lib/CodeGen/TwoAddressInstructionPass.cpp b/lib/CodeGen/TwoAddressInstructionPass.cpp index 3860e0b..f1c0bb1 100644 --- a/lib/CodeGen/TwoAddressInstructionPass.cpp +++ b/lib/CodeGen/TwoAddressInstructionPass.cpp @@ -943,7 +943,7 @@ TryInstructionTransform(MachineBasicBlock::iterator &mi, // Unfold the load. DEBUG(dbgs() << "2addr: UNFOLDING: " << *mi); const TargetRegisterClass *RC = - UnfoldTID.OpInfo[LoadRegIndex].getRegClass(TRI); + TII->getRegClass(UnfoldTID, LoadRegIndex, TRI); unsigned Reg = MRI->createVirtualRegister(RC); SmallVector NewMIs; if (!TII->unfoldMemoryOperand(MF, mi, Reg, diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/lib/Target/ARM/ARMBaseRegisterInfo.cpp index 92c98da..b765476 100644 --- a/lib/Target/ARM/ARMBaseRegisterInfo.cpp +++ b/lib/Target/ARM/ARMBaseRegisterInfo.cpp @@ -1112,7 +1112,7 @@ materializeFrameBaseRegister(MachineBasicBlock *MBB, const TargetInstrDesc &TID = TII.get(ADDriOpc); MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo(); - MRI.constrainRegClass(BaseReg, TID.OpInfo[0].getRegClass(this)); + MRI.constrainRegClass(BaseReg, TII.getRegClass(TID, 0, this)); MachineInstrBuilder MIB = BuildMI(*MBB, Ins, DL, TID, BaseReg) .addFrameIndex(FrameIdx).addImm(Offset); diff --git a/lib/Target/ARM/ARMLoadStoreOptimizer.cpp b/lib/Target/ARM/ARMLoadStoreOptimizer.cpp index f4645f1..e4ec681 100644 --- a/lib/Target/ARM/ARMLoadStoreOptimizer.cpp +++ b/lib/Target/ARM/ARMLoadStoreOptimizer.cpp @@ -1673,7 +1673,7 @@ bool ARMPreAllocLoadStoreOpt::RescheduleOps(MachineBasicBlock *MBB, Ops.pop_back(); const TargetInstrDesc &TID = TII->get(NewOpc); - const TargetRegisterClass *TRC = TID.OpInfo[0].getRegClass(TRI); + const TargetRegisterClass *TRC = TII->getRegClass(TID, 0, TRI); MRI->constrainRegClass(EvenReg, TRC); MRI->constrainRegClass(OddReg, TRC); diff --git a/lib/Target/ARM/MLxExpansionPass.cpp b/lib/Target/ARM/MLxExpansionPass.cpp index f6d0242..fc22861 100644 --- a/lib/Target/ARM/MLxExpansionPass.cpp +++ b/lib/Target/ARM/MLxExpansionPass.cpp @@ -220,7 +220,7 @@ MLxExpansion::ExpandFPMLxInstruction(MachineBasicBlock &MBB, MachineInstr *MI, const TargetInstrDesc &TID1 = TII->get(MulOpc); const TargetInstrDesc &TID2 = TII->get(AddSubOpc); - unsigned TmpReg = MRI->createVirtualRegister(TID1.getRegClass(0, TRI)); + unsigned TmpReg = MRI->createVirtualRegister(TII->getRegClass(TID1, 0, TRI)); MachineInstrBuilder MIB = BuildMI(MBB, *MI, MI->getDebugLoc(), TID1, TmpReg) .addReg(Src1Reg, getKillRegState(Src1Kill)) diff --git a/lib/Target/Blackfin/BlackfinISelDAGToDAG.cpp b/lib/Target/Blackfin/BlackfinISelDAGToDAG.cpp index 42659ae..d587a2f 100644 --- a/lib/Target/Blackfin/BlackfinISelDAGToDAG.cpp +++ b/lib/Target/Blackfin/BlackfinISelDAGToDAG.cpp @@ -154,13 +154,13 @@ void BlackfinDAGToDAGISel::FixRegisterClasses(SelectionDAG &DAG) { if (UI.getUse().getResNo() >= DefTID.getNumDefs()) continue; const TargetRegisterClass *DefRC = - DefTID.OpInfo[UI.getUse().getResNo()].getRegClass(TRI); + TII.getRegClass(DefTID, UI.getUse().getResNo(), TRI); const TargetInstrDesc &UseTID = TII.get(UI->getMachineOpcode()); if (UseTID.getNumDefs()+UI.getOperandNo() >= UseTID.getNumOperands()) continue; const TargetRegisterClass *UseRC = - UseTID.OpInfo[UseTID.getNumDefs()+UI.getOperandNo()].getRegClass(TRI); + TII.getRegClass(UseTID, UseTID.getNumDefs()+UI.getOperandNo(), TRI); if (!DefRC || !UseRC) continue; // We cannot copy CC <-> !(CC/D) diff --git a/lib/Target/TargetInstrInfo.cpp b/lib/Target/TargetInstrInfo.cpp index d4b7697..2cb89f4 100644 --- a/lib/Target/TargetInstrInfo.cpp +++ b/lib/Target/TargetInstrInfo.cpp @@ -21,24 +21,6 @@ using namespace llvm; //===----------------------------------------------------------------------===// -// TargetOperandInfo -//===----------------------------------------------------------------------===// - -/// getRegClass - Get the register class for the operand, handling resolution -/// of "symbolic" pointer register classes etc. If this is not a register -/// operand, this returns null. -const TargetRegisterClass * -TargetOperandInfo::getRegClass(const TargetRegisterInfo *TRI) const { - if (isLookupPtrRegClass()) - return TRI->getPointerRegClass(RegClass); - // Instructions like INSERT_SUBREG do not have fixed register classes. - if (RegClass < 0) - return 0; - // Otherwise just look it up normally. - return TRI->getRegClass(RegClass); -} - -//===----------------------------------------------------------------------===// // TargetInstrInfo //===----------------------------------------------------------------------===// @@ -50,6 +32,24 @@ TargetInstrInfo::TargetInstrInfo(const TargetInstrDesc* Desc, TargetInstrInfo::~TargetInstrInfo() { } +const TargetRegisterClass* +TargetInstrInfo::getRegClass(const TargetInstrDesc &TID, unsigned OpNum, + const TargetRegisterInfo *TRI) const { + if (OpNum >= TID.getNumOperands()) + return 0; + + short RegClass = TID.OpInfo[OpNum].RegClass; + if (TID.OpInfo[OpNum].isLookupPtrRegClass()) + return TRI->getPointerRegClass(RegClass); + + // Instructions like INSERT_SUBREG do not have fixed register classes. + if (RegClass < 0) + return 0; + + // Otherwise just look it up normally. + return TRI->getRegClass(RegClass); +} + unsigned TargetInstrInfo::getNumMicroOps(const InstrItineraryData *ItinData, const MachineInstr *MI) const { diff --git a/lib/Target/X86/X86InstrInfo.cpp b/lib/Target/X86/X86InstrInfo.cpp index aebf8dc..d4c279c 100644 --- a/lib/Target/X86/X86InstrInfo.cpp +++ b/lib/Target/X86/X86InstrInfo.cpp @@ -2274,7 +2274,7 @@ X86InstrInfo::foldMemoryOperandImpl(MachineFunction &MF, return NULL; bool NarrowToMOV32rm = false; if (Size) { - unsigned RCSize = MI->getDesc().OpInfo[i].getRegClass(&RI)->getSize(); + unsigned RCSize = getRegClass(MI->getDesc(), i, &RI)->getSize(); if (Size < RCSize) { // Check if it's safe to fold the load. If the size of the object is // narrower than the load width, then it's not. @@ -2590,8 +2590,7 @@ bool X86InstrInfo::unfoldMemoryOperand(MachineFunction &MF, MachineInstr *MI, UnfoldStore &= FoldedStore; const TargetInstrDesc &TID = get(Opc); - const TargetOperandInfo &TOI = TID.OpInfo[Index]; - const TargetRegisterClass *RC = TOI.getRegClass(&RI); + const TargetRegisterClass *RC = getRegClass(TID, Index, &RI); if (!MI->hasOneMemOperand() && RC == &X86::VR128RegClass && !TM.getSubtarget().isUnalignedMemAccessFast()) @@ -2686,7 +2685,7 @@ bool X86InstrInfo::unfoldMemoryOperand(MachineFunction &MF, MachineInstr *MI, // Emit the store instruction. if (UnfoldStore) { - const TargetRegisterClass *DstRC = TID.OpInfo[0].getRegClass(&RI); + const TargetRegisterClass *DstRC = getRegClass(TID, 0, &RI); std::pair MMOs = MF.extractStoreMemRefs(MI->memoperands_begin(), @@ -2712,7 +2711,7 @@ X86InstrInfo::unfoldMemoryOperand(SelectionDAG &DAG, SDNode *N, bool FoldedLoad = I->second.second & (1 << 4); bool FoldedStore = I->second.second & (1 << 5); const TargetInstrDesc &TID = get(Opc); - const TargetRegisterClass *RC = TID.OpInfo[Index].getRegClass(&RI); + const TargetRegisterClass *RC = getRegClass(TID, Index, &RI); unsigned NumDefs = TID.NumDefs; std::vector AddrOps; std::vector BeforeOps; @@ -2758,7 +2757,7 @@ X86InstrInfo::unfoldMemoryOperand(SelectionDAG &DAG, SDNode *N, std::vector VTs; const TargetRegisterClass *DstRC = 0; if (TID.getNumDefs() > 0) { - DstRC = TID.OpInfo[0].getRegClass(&RI); + DstRC = getRegClass(TID, 0, &RI); VTs.push_back(*DstRC->vt_begin()); } for (unsigned i = 0, e = N->getNumValues(); i != e; ++i) { -- cgit v1.1 From df8fe9901df829a02d1257121f35a78a434aca0d Mon Sep 17 00:00:00 2001 From: Jim Grosbach Date: Mon, 27 Jun 2011 21:38:03 +0000 Subject: ARM Asm parsing of Thumb2 move immediate. Thumb2 MOV mnemonic can accept both cc_out and predication. We don't (yet) encode the instruction properly, but this gets the parsing part. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133945 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 48daad0..8fe504f 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -1826,6 +1826,7 @@ static StringRef SplitMnemonic(StringRef Mnemonic, void ARMAsmParser:: GetMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet, bool &CanAcceptPredicationCode) { + bool isThumbOne = TM.getSubtarget().isThumb1Only(); bool isThumb = TM.getSubtarget().isThumb(); if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" || @@ -1836,7 +1837,7 @@ GetMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet, Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" || Mnemonic == "sbc" || Mnemonic == "mla" || Mnemonic == "umull" || Mnemonic == "eor" || Mnemonic == "smlal" || - (Mnemonic == "mov" && !isThumb)) { + (Mnemonic == "mov" && !isThumbOne)) { CanAcceptCarrySet = true; } else { CanAcceptCarrySet = false; @@ -1856,7 +1857,7 @@ GetMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet, if (isThumb) if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" || Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp" || - Mnemonic == "mov") + (Mnemonic == "mov" && isThumbOne)) CanAcceptPredicationCode = false; } -- cgit v1.1 From f227b50a8e30598464c244a675d8e857b62a52ac Mon Sep 17 00:00:00 2001 From: Jakub Staszak Date: Mon, 27 Jun 2011 21:51:12 +0000 Subject: Calculate GetBestDestForJumpOnUndef correctly. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133946 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Scalar/JumpThreading.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/Transforms/Scalar/JumpThreading.cpp b/lib/Transforms/Scalar/JumpThreading.cpp index cf18ff0..b500d5b 100644 --- a/lib/Transforms/Scalar/JumpThreading.cpp +++ b/lib/Transforms/Scalar/JumpThreading.cpp @@ -600,8 +600,10 @@ static unsigned GetBestDestForJumpOnUndef(BasicBlock *BB) { for (unsigned i = 1, e = BBTerm->getNumSuccessors(); i != e; ++i) { TestBB = BBTerm->getSuccessor(i); unsigned NumPreds = std::distance(pred_begin(TestBB), pred_end(TestBB)); - if (NumPreds < MinNumPreds) + if (NumPreds < MinNumPreds) { MinSucc = i; + MinNumPreds = NumPreds; + } } return MinSucc; -- cgit v1.1 From 81ce26a410a2bcd751f40022d78e20c95bf7b60e Mon Sep 17 00:00:00 2001 From: Eric Christopher Date: Mon, 27 Jun 2011 22:30:14 +0000 Subject: Fix this test to actually check something and be able to be compiled. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133952 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/FrontendC/ARM/inline-asm-multichar.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/FrontendC/ARM/inline-asm-multichar.c b/test/FrontendC/ARM/inline-asm-multichar.c index 7e2eeef..bd88390 100644 --- a/test/FrontendC/ARM/inline-asm-multichar.c +++ b/test/FrontendC/ARM/inline-asm-multichar.c @@ -1,11 +1,11 @@ -// RUN: %llvmgcc -S -march=armv7a %s +// RUN: %llvmgcc -S -march=armv7a %s | FileCheck %s // XFAIL: * // XTARGET: arm int t1() { static float k = 1.0f; -CHECK: call void asm sideeffect "flds s15, $0 \0A", "*^Uv,~{s15}" + // CHECK: "flds s15, $0 \0A", "*^Uv,~{s15}" __asm__ volatile ("flds s15, %[k] \n" :: [k] "Uv,m" (k) : "s15"); return 0; } -- cgit v1.1 From 016c5829a5dacc3b28cb264b4b6d166552e3d568 Mon Sep 17 00:00:00 2001 From: Devang Patel Date: Mon, 27 Jun 2011 22:32:04 +0000 Subject: During bottom up fast-isel, instructions emitted to materalize registers are at top of basic block and do not have debug location. This may misguide debugger while entering the basic block and sometimes debugger provides semi useful view of current location to developer by picking up previous known location as current location. Assign a sensible location to the first instruction in a basic block, if it does not have one location derived from source file, so that debugger can provide meaningful user experience to developers in edge cases. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133953 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CodeGen/FastISel.h | 4 + lib/CodeGen/SelectionDAG/FastISel.cpp | 22 +++++ lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 2 + test/CodeGen/X86/dbg-materialized-reg-loc.ll | 120 ++++++++++++++++++++++++++ 4 files changed, 148 insertions(+) create mode 100644 test/CodeGen/X86/dbg-materialized-reg-loc.ll diff --git a/include/llvm/CodeGen/FastISel.h b/include/llvm/CodeGen/FastISel.h index 962a4e2..14960a3 100644 --- a/include/llvm/CodeGen/FastISel.h +++ b/include/llvm/CodeGen/FastISel.h @@ -118,6 +118,10 @@ public: DebugLoc DL; }; + /// recomputeDebugLocForMaterializedRegs - Recompute debug location for + /// very first instruction in a basic block. + void recomputeDebugLocForMaterializedRegs(); + /// enterLocalValueArea - Prepare InsertPt to begin inserting instructions /// into the local value area and return the old insert position. SavePoint enterLocalValueArea(); diff --git a/lib/CodeGen/SelectionDAG/FastISel.cpp b/lib/CodeGen/SelectionDAG/FastISel.cpp index 8ae75f5..a7d629e 100644 --- a/lib/CodeGen/SelectionDAG/FastISel.cpp +++ b/lib/CodeGen/SelectionDAG/FastISel.cpp @@ -292,6 +292,28 @@ void FastISel::recomputeInsertPt() { ++FuncInfo.InsertPt; } +/// recomputeDebugLocForMaterializedRegs - Recompute debug location for +/// very first instruction in a basic block. All instructions emitted +/// to materialize registers do not have location information, see +/// enterLocalValueArea(), becase they may not be emited at the right +/// location. +void FastISel::recomputeDebugLocForMaterializedRegs() { + if (!getLastLocalValue()) + return; + MachineInstr *First = FuncInfo.MBB->getFirstNonPHI(); + if (!First->getDebugLoc().isUnknown()) + return; + + for (MachineBasicBlock::iterator I = FuncInfo.MBB->begin(), + E = FuncInfo.MBB->end(); I != E; ++I) { + DebugLoc DL = I->getDebugLoc(); + if (!DL.isUnknown()) { + First->setDebugLoc(DL); + return; + } + } +} + FastISel::SavePoint FastISel::enterLocalValueArea() { MachineBasicBlock::iterator OldInsertPt = FuncInfo.InsertPt; DebugLoc OldDL = DL; diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index dc8044b..7a9439f 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -964,6 +964,8 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) { else ++NumFastIselBlocks; + if (FastIS) + FastIS->recomputeDebugLocForMaterializedRegs(); if (Begin != BI) { // Run SelectionDAG instruction selection on the remainder of the block // not handled by FastISel. If FastISel is not run, this is the entire diff --git a/test/CodeGen/X86/dbg-materialized-reg-loc.ll b/test/CodeGen/X86/dbg-materialized-reg-loc.ll new file mode 100644 index 0000000..9fa6a67 --- /dev/null +++ b/test/CodeGen/X86/dbg-materialized-reg-loc.ll @@ -0,0 +1,120 @@ +; RUN: llc -O0 < %s | FileCheck %s +; Radar 9223880 +; CHECK: .loc 1 17 64 +; CHECK: movl $0, %esi + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" +target triple = "x86_64-apple-macosx10.7.0" + +%class.LanguageRuntime = type opaque +%class.Process = type { i8 } + +define zeroext i1 @_Z15SetDynamicValuev() uwtable ssp { +entry: + %retval = alloca i1, align 1 + %process = alloca %class.Process*, align 8 + %cpp_runtime = alloca %class.LanguageRuntime*, align 8 + %objc_runtime = alloca %class.LanguageRuntime*, align 8 + %call = call zeroext i1 @_Z24IsPointerOrReferenceTypev(), !dbg !15 + br i1 %call, label %if.end, label %if.then, !dbg !15 + +if.then: ; preds = %entry + store i1 false, i1* %retval, !dbg !17 + br label %return, !dbg !17 + +if.end: ; preds = %entry + call void @llvm.dbg.declare(metadata !{%class.Process** %process}, metadata !18), !dbg !20 + %call1 = call %class.Process* @_Z10GetProcessv(), !dbg !21 + store %class.Process* %call1, %class.Process** %process, align 8, !dbg !21 + %tmp = load %class.Process** %process, align 8, !dbg !22 + %tobool = icmp ne %class.Process* %tmp, null, !dbg !22 + br i1 %tobool, label %if.end3, label %if.then2, !dbg !22 + +if.then2: ; preds = %if.end + store i1 false, i1* %retval, !dbg !23 + br label %return, !dbg !23 + +if.end3: ; preds = %if.end + call void @llvm.dbg.declare(metadata !{%class.LanguageRuntime** %cpp_runtime}, metadata !24), !dbg !25 + %tmp5 = load %class.Process** %process, align 8, !dbg !26 + %call6 = call %class.LanguageRuntime* @_ZN7Process18GetLanguageRuntimeEi(%class.Process* %tmp5, i32 0), !dbg !26 + store %class.LanguageRuntime* %call6, %class.LanguageRuntime** %cpp_runtime, align 8, !dbg !26 + %tmp7 = load %class.LanguageRuntime** %cpp_runtime, align 8, !dbg !27 + %tobool8 = icmp ne %class.LanguageRuntime* %tmp7, null, !dbg !27 + br i1 %tobool8, label %if.then9, label %if.end10, !dbg !27 + +if.then9: ; preds = %if.end3 + store i1 true, i1* %retval, !dbg !28 + br label %return, !dbg !28 + +if.end10: ; preds = %if.end3 + call void @llvm.dbg.declare(metadata !{%class.LanguageRuntime** %objc_runtime}, metadata !30), !dbg !31 + %tmp12 = load %class.Process** %process, align 8, !dbg !32 + %call13 = call %class.LanguageRuntime* @_ZN7Process18GetLanguageRuntimeEi(%class.Process* %tmp12, i32 1), !dbg !32 + store %class.LanguageRuntime* %call13, %class.LanguageRuntime** %objc_runtime, align 8, !dbg !32 + %tmp14 = load %class.LanguageRuntime** %objc_runtime, align 8, !dbg !33 + %tobool15 = icmp ne %class.LanguageRuntime* %tmp14, null, !dbg !33 + br i1 %tobool15, label %if.then16, label %if.end17, !dbg !33 + +if.then16: ; preds = %if.end10 + store i1 true, i1* %retval, !dbg !34 + br label %return, !dbg !34 + +if.end17: ; preds = %if.end10 + store i1 false, i1* %retval, !dbg !36 + br label %return, !dbg !36 + +return: ; preds = %if.end17, %if.then16, %if.then9, %if.then2, %if.then + %0 = load i1* %retval, !dbg !37 + ret i1 %0, !dbg !37 +} + +declare zeroext i1 @_Z24IsPointerOrReferenceTypev() + +declare void @llvm.dbg.declare(metadata, metadata) nounwind readnone + +declare %class.Process* @_Z10GetProcessv() + +declare %class.LanguageRuntime* @_ZN7Process18GetLanguageRuntimeEi(%class.Process*, i32) + +!llvm.dbg.cu = !{!0} +!llvm.dbg.sp = !{!1, !6} + +!0 = metadata !{i32 589841, i32 0, i32 4, metadata !"my_vo.cpp", metadata !"/private/tmp", metadata !"clang version 3.0 (trunk 133629)", i1 true, i1 false, metadata !"", i32 0} ; [ DW_TAG_compile_unit ] +!1 = metadata !{i32 589870, i32 0, metadata !2, metadata !"SetDynamicValue", metadata !"SetDynamicValue", metadata !"_Z15SetDynamicValuev", metadata !2, i32 9, metadata !3, i1 false, i1 true, i32 0, i32 0, i32 0, i32 256, i1 false, i1 ()* @_Z15SetDynamicValuev, null, null} ; [ DW_TAG_subprogram ] +!2 = metadata !{i32 589865, metadata !"my_vo.cpp", metadata !"/private/tmp", metadata !0} ; [ DW_TAG_file_type ] +!3 = metadata !{i32 589845, metadata !2, metadata !"", metadata !2, i32 0, i64 0, i64 0, i32 0, i32 0, i32 0, metadata !4, i32 0, i32 0} ; [ DW_TAG_subroutine_type ] +!4 = metadata !{metadata !5} +!5 = metadata !{i32 589860, metadata !0, metadata !"bool", null, i32 0, i64 8, i64 8, i64 0, i32 0, i32 2} ; [ DW_TAG_base_type ] +!6 = metadata !{i32 589870, i32 0, metadata !7, metadata !"GetLanguageRuntime", metadata !"GetLanguageRuntime", metadata !"_ZN7Process18GetLanguageRuntimeEi", metadata !2, i32 4, metadata !9, i1 false, i1 false, i32 0, i32 0, null, i32 256, i1 false, null, null} ; [ DW_TAG_subprogram ] +!7 = metadata !{i32 589826, metadata !0, metadata !"Process", metadata !2, i32 2, i64 8, i64 8, i32 0, i32 0, null, metadata !8, i32 0, null, null} ; [ DW_TAG_class_type ] +!8 = metadata !{metadata !6} +!9 = metadata !{i32 589845, metadata !2, metadata !"", metadata !2, i32 0, i64 0, i64 0, i32 0, i32 0, i32 0, metadata !10, i32 0, i32 0} ; [ DW_TAG_subroutine_type ] +!10 = metadata !{metadata !11, metadata !13, metadata !14} +!11 = metadata !{i32 589839, metadata !0, metadata !"", null, i32 0, i64 64, i64 64, i64 0, i32 0, metadata !12} ; [ DW_TAG_pointer_type ] +!12 = metadata !{i32 589843, metadata !0, metadata !"LanguageRuntime", metadata !2, i32 1, i64 0, i64 0, i32 0, i32 4, i32 0, null, i32 0, i32 0} ; [ DW_TAG_structure_type ] +!13 = metadata !{i32 589839, metadata !0, metadata !"", i32 0, i32 0, i64 64, i64 64, i64 0, i32 64, metadata !7} ; [ DW_TAG_pointer_type ] +!14 = metadata !{i32 589860, metadata !0, metadata !"int", null, i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] +!15 = metadata !{i32 10, i32 3, metadata !16, null} +!16 = metadata !{i32 589835, metadata !1, i32 9, i32 24, metadata !2, i32 0} ; [ DW_TAG_lexical_block ] +!17 = metadata !{i32 11, i32 5, metadata !16, null} +!18 = metadata !{i32 590080, metadata !16, metadata !"process", metadata !2, i32 13, metadata !19, i32 0} ; [ DW_TAG_auto_variable ] +!19 = metadata !{i32 589839, metadata !0, metadata !"", null, i32 0, i64 64, i64 64, i64 0, i32 0, metadata !7} ; [ DW_TAG_pointer_type ] +!20 = metadata !{i32 13, i32 12, metadata !16, null} +!21 = metadata !{i32 13, i32 34, metadata !16, null} +!22 = metadata !{i32 14, i32 3, metadata !16, null} +!23 = metadata !{i32 15, i32 5, metadata !16, null} +!24 = metadata !{i32 590080, metadata !16, metadata !"cpp_runtime", metadata !2, i32 17, metadata !11, i32 0} ; [ DW_TAG_auto_variable ] +!25 = metadata !{i32 17, i32 20, metadata !16, null} +!26 = metadata !{i32 17, i32 64, metadata !16, null} +!27 = metadata !{i32 18, i32 3, metadata !16, null} +!28 = metadata !{i32 19, i32 5, metadata !29, null} +!29 = metadata !{i32 589835, metadata !16, i32 18, i32 20, metadata !2, i32 1} ; [ DW_TAG_lexical_block ] +!30 = metadata !{i32 590080, metadata !16, metadata !"objc_runtime", metadata !2, i32 22, metadata !11, i32 0} ; [ DW_TAG_auto_variable ] +!31 = metadata !{i32 22, i32 20, metadata !16, null} +!32 = metadata !{i32 22, i32 65, metadata !16, null} +!33 = metadata !{i32 23, i32 3, metadata !16, null} +!34 = metadata !{i32 24, i32 5, metadata !35, null} +!35 = metadata !{i32 589835, metadata !16, i32 23, i32 21, metadata !2, i32 2} ; [ DW_TAG_lexical_block ] +!36 = metadata !{i32 26, i32 3, metadata !16, null} +!37 = metadata !{i32 27, i32 1, metadata !16, null} -- cgit v1.1 From 26f448079f2dc070da637e346a0635ad3127df7d Mon Sep 17 00:00:00 2001 From: Chad Rosier Date: Mon, 27 Jun 2011 22:54:29 +0000 Subject: =?UTF-8?q?Revert=20r133516=20"Remove=20some=20unnecessary=20uses?= =?UTF-8?q?=20of=20c=5Fstr()."=20This=20was=20causing=20compile-time=20fai?= =?UTF-8?q?lures=20for=20some=20of=20the=20Objc=20and=20Obj-C++=20benchmar?= =?UTF-8?q?ks.=20=20The=20specific=20errors=20were=20of=20the=20form:=20"l?= =?UTF-8?q?d:=20duplicate=20symbol=20=E2=80=A6"=20rdar://9660124?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133955 91177308-0d34-0410-b5e6-96231b3b80d8 --- tools/lto/LTOModule.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/lto/LTOModule.cpp b/tools/lto/LTOModule.cpp index c899555..8f2b1f4 100644 --- a/tools/lto/LTOModule.cpp +++ b/tools/lto/LTOModule.cpp @@ -208,7 +208,7 @@ void LTOModule::addObjCClass(GlobalVariable *clgv) { if (objcClassNameFromExpression(c->getOperand(1), superclassName)) { NameAndAttributes info; StringMap::value_type &entry = - _undefines.GetOrCreateValue(superclassName); + _undefines.GetOrCreateValue(superclassName.c_str()); if (!entry.getValue().name) { const char *symbolName = entry.getKey().data(); info.name = symbolName; @@ -220,7 +220,7 @@ void LTOModule::addObjCClass(GlobalVariable *clgv) { std::string className; if (objcClassNameFromExpression(c->getOperand(2), className)) { StringSet::value_type &entry = - _defines.GetOrCreateValue(className); + _defines.GetOrCreateValue(className.c_str()); entry.setValue(1); NameAndAttributes info; info.name = entry.getKey().data(); @@ -243,7 +243,7 @@ void LTOModule::addObjCCategory(GlobalVariable *clgv) { NameAndAttributes info; StringMap::value_type &entry = - _undefines.GetOrCreateValue(targetclassName); + _undefines.GetOrCreateValue(targetclassName.c_str()); if (entry.getValue().name) return; @@ -264,7 +264,7 @@ void LTOModule::addObjCClassRef(GlobalVariable *clgv) { NameAndAttributes info; StringMap::value_type &entry = - _undefines.GetOrCreateValue(targetclassName); + _undefines.GetOrCreateValue(targetclassName.c_str()); if (entry.getValue().name) return; @@ -375,7 +375,7 @@ void LTOModule::addDefinedSymbol(GlobalValue *def, Mangler &mangler, // add to table of symbols NameAndAttributes info; - StringSet::value_type &entry = _defines.GetOrCreateValue(Buffer); + StringSet::value_type &entry = _defines.GetOrCreateValue(Buffer.c_str()); entry.setValue(1); StringRef Name = entry.getKey(); @@ -436,7 +436,7 @@ void LTOModule::addPotentialUndefinedSymbol(GlobalValue *decl, mangler.getNameWithPrefix(name, decl, false); StringMap::value_type &entry = - _undefines.GetOrCreateValue(name); + _undefines.GetOrCreateValue(name.c_str()); // we already have the symbol if (entry.getValue().name) -- cgit v1.1 From 156d460c758463eb407590cba2371857daf27d8a Mon Sep 17 00:00:00 2001 From: Andrew Trick Date: Mon, 27 Jun 2011 23:17:44 +0000 Subject: indvars -disable-iv-rewrite: run RLEV after SimplifyIVUsers for a bit more control over the order SCEVs are evaluated. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133959 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Scalar/IndVarSimplify.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/Transforms/Scalar/IndVarSimplify.cpp b/lib/Transforms/Scalar/IndVarSimplify.cpp index 1d79339..1a87b15 100644 --- a/lib/Transforms/Scalar/IndVarSimplify.cpp +++ b/lib/Transforms/Scalar/IndVarSimplify.cpp @@ -1158,8 +1158,12 @@ bool IndVarSimplify::runOnLoop(Loop *L, LPPassManager &LPM) { // Create a rewriter object which we'll use to transform the code with. SCEVExpander Rewriter(*SE); - if (DisableIVRewrite) + + // Eliminate redundant IV users. + if (DisableIVRewrite) { Rewriter.disableCanonicalMode(); + SimplifyIVUsersNoRewrite(L, Rewriter); + } // Check to see if this loop has a computable loop-invariant execution count. // If so, this means that we can compute the final value of any expressions @@ -1171,9 +1175,7 @@ bool IndVarSimplify::runOnLoop(Loop *L, LPPassManager &LPM) { RewriteLoopExitValues(L, Rewriter); // Eliminate redundant IV users. - if (DisableIVRewrite) - SimplifyIVUsersNoRewrite(L, Rewriter); - else + if (!DisableIVRewrite) SimplifyIVUsers(Rewriter); // Compute the type of the largest recurrence expression, and decide whether -- cgit v1.1 From f10711fb8c8b5596e973bcc27b5af6203fec34b4 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Mon, 27 Jun 2011 23:40:45 +0000 Subject: Remove the experimental (and unused) pre-ra splitting pass. Greedy regalloc can split live ranges. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133962 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CodeGen/Passes.h | 2 - include/llvm/InitializePasses.h | 1 - lib/CodeGen/CodeGen.cpp | 1 - lib/CodeGen/PreAllocSplitting.cpp | 1430 ------------------------------------ lib/CodeGen/RegAllocLinearScan.cpp | 9 - test/CodeGen/X86/pre-split1.ll | 24 - test/CodeGen/X86/pre-split10.ll | 51 -- test/CodeGen/X86/pre-split11.ll | 34 - test/CodeGen/X86/pre-split4.ll | 26 - test/CodeGen/X86/pre-split5.ll | 56 -- test/CodeGen/X86/pre-split6.ll | 36 - test/CodeGen/X86/pre-split7.ll | 34 - test/CodeGen/X86/pre-split8.ll | 35 - test/CodeGen/X86/pre-split9.ll | 38 - 14 files changed, 1777 deletions(-) delete mode 100644 lib/CodeGen/PreAllocSplitting.cpp delete mode 100644 test/CodeGen/X86/pre-split1.ll delete mode 100644 test/CodeGen/X86/pre-split10.ll delete mode 100644 test/CodeGen/X86/pre-split11.ll delete mode 100644 test/CodeGen/X86/pre-split4.ll delete mode 100644 test/CodeGen/X86/pre-split5.ll delete mode 100644 test/CodeGen/X86/pre-split6.ll delete mode 100644 test/CodeGen/X86/pre-split7.ll delete mode 100644 test/CodeGen/X86/pre-split8.ll delete mode 100644 test/CodeGen/X86/pre-split9.ll diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h index b0e9213..e7928cb 100644 --- a/include/llvm/CodeGen/Passes.h +++ b/include/llvm/CodeGen/Passes.h @@ -73,8 +73,6 @@ namespace llvm { /// This pass is still in development extern char &StrongPHIEliminationID; - extern char &PreAllocSplittingID; - /// LiveStacks pass. An analysis keeping track of the liveness of stack slots. extern char &LiveStacksID; diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h index 89d0ac8..dfd9246 100644 --- a/include/llvm/InitializePasses.h +++ b/include/llvm/InitializePasses.h @@ -177,7 +177,6 @@ void initializePostDomOnlyViewerPass(PassRegistry&); void initializePostDomPrinterPass(PassRegistry&); void initializePostDomViewerPass(PassRegistry&); void initializePostDominatorTreePass(PassRegistry&); -void initializePreAllocSplittingPass(PassRegistry&); void initializePreVerifierPass(PassRegistry&); void initializePrintDbgInfoPass(PassRegistry&); void initializePrintFunctionPassPass(PassRegistry&); diff --git a/lib/CodeGen/CodeGen.cpp b/lib/CodeGen/CodeGen.cpp index 35923c6..489746c 100644 --- a/lib/CodeGen/CodeGen.cpp +++ b/lib/CodeGen/CodeGen.cpp @@ -37,7 +37,6 @@ void llvm::initializeCodeGen(PassRegistry &Registry) { initializeOptimizePHIsPass(Registry); initializePHIEliminationPass(Registry); initializePeepholeOptimizerPass(Registry); - initializePreAllocSplittingPass(Registry); initializeProcessImplicitDefsPass(Registry); initializePEIPass(Registry); initializeRALinScanPass(Registry); diff --git a/lib/CodeGen/PreAllocSplitting.cpp b/lib/CodeGen/PreAllocSplitting.cpp deleted file mode 100644 index 26c141d..0000000 --- a/lib/CodeGen/PreAllocSplitting.cpp +++ /dev/null @@ -1,1430 +0,0 @@ -//===-- PreAllocSplitting.cpp - Pre-allocation Interval Spltting Pass. ----===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the machine instruction level pre-register allocation -// live interval splitting pass. It finds live interval barriers, i.e. -// instructions which will kill all physical registers in certain register -// classes, and split all live intervals which cross the barrier. -// -//===----------------------------------------------------------------------===// - -#define DEBUG_TYPE "pre-alloc-split" -#include "VirtRegMap.h" -#include "RegisterCoalescer.h" -#include "llvm/CodeGen/CalcSpillWeights.h" -#include "llvm/CodeGen/LiveIntervalAnalysis.h" -#include "llvm/CodeGen/LiveStackAnalysis.h" -#include "llvm/CodeGen/MachineDominators.h" -#include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/MachineLoopInfo.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/Passes.h" -#include "llvm/Target/TargetInstrInfo.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetOptions.h" -#include "llvm/Target/TargetRegisterInfo.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/DepthFirstIterator.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/Statistic.h" -using namespace llvm; - -static cl::opt PreSplitLimit("pre-split-limit", cl::init(-1), cl::Hidden); -static cl::opt DeadSplitLimit("dead-split-limit", cl::init(-1), - cl::Hidden); -static cl::opt RestoreFoldLimit("restore-fold-limit", cl::init(-1), - cl::Hidden); - -STATISTIC(NumSplits, "Number of intervals split"); -STATISTIC(NumRemats, "Number of intervals split by rematerialization"); -STATISTIC(NumFolds, "Number of intervals split with spill folding"); -STATISTIC(NumRestoreFolds, "Number of intervals split with restore folding"); -STATISTIC(NumRenumbers, "Number of intervals renumbered into new registers"); -STATISTIC(NumDeadSpills, "Number of dead spills removed"); - -namespace { - class PreAllocSplitting : public MachineFunctionPass { - MachineFunction *CurrMF; - const TargetMachine *TM; - const TargetInstrInfo *TII; - const TargetRegisterInfo* TRI; - MachineFrameInfo *MFI; - MachineRegisterInfo *MRI; - SlotIndexes *SIs; - LiveIntervals *LIs; - LiveStacks *LSs; - VirtRegMap *VRM; - - // Barrier - Current barrier being processed. - MachineInstr *Barrier; - - // BarrierMBB - Basic block where the barrier resides in. - MachineBasicBlock *BarrierMBB; - - // Barrier - Current barrier index. - SlotIndex BarrierIdx; - - // CurrLI - Current live interval being split. - LiveInterval *CurrLI; - - // CurrSLI - Current stack slot live interval. - LiveInterval *CurrSLI; - - // CurrSValNo - Current val# for the stack slot live interval. - VNInfo *CurrSValNo; - - // IntervalSSMap - A map from live interval to spill slots. - DenseMap IntervalSSMap; - - // Def2SpillMap - A map from a def instruction index to spill index. - DenseMap Def2SpillMap; - - public: - static char ID; - PreAllocSplitting() : MachineFunctionPass(ID) { - initializePreAllocSplittingPass(*PassRegistry::getPassRegistry()); - } - - virtual bool runOnMachineFunction(MachineFunction &MF); - - virtual void getAnalysisUsage(AnalysisUsage &AU) const { - AU.setPreservesCFG(); - AU.addRequired(); - AU.addPreserved(); - AU.addRequired(); - AU.addPreserved(); - AU.addRequired(); - AU.addPreserved(); - AU.addPreserved(); - AU.addPreserved(); - AU.addPreservedID(StrongPHIEliminationID); - AU.addPreservedID(PHIEliminationID); - AU.addRequired(); - AU.addRequired(); - AU.addRequired(); - AU.addPreserved(); - AU.addPreserved(); - AU.addPreserved(); - MachineFunctionPass::getAnalysisUsage(AU); - } - - virtual void releaseMemory() { - IntervalSSMap.clear(); - Def2SpillMap.clear(); - } - - virtual const char *getPassName() const { - return "Pre-Register Allocaton Live Interval Splitting"; - } - - /// print - Implement the dump method. - virtual void print(raw_ostream &O, const Module* M = 0) const { - LIs->print(O, M); - } - - - private: - - MachineBasicBlock::iterator - findSpillPoint(MachineBasicBlock*, MachineInstr*, MachineInstr*, - SmallPtrSet&); - - MachineBasicBlock::iterator - findRestorePoint(MachineBasicBlock*, MachineInstr*, SlotIndex, - SmallPtrSet&); - - int CreateSpillStackSlot(unsigned, const TargetRegisterClass *); - - bool IsAvailableInStack(MachineBasicBlock*, unsigned, - SlotIndex, SlotIndex, - SlotIndex&, int&) const; - - void UpdateSpillSlotInterval(VNInfo*, SlotIndex, SlotIndex); - - bool SplitRegLiveInterval(LiveInterval*); - - bool SplitRegLiveIntervals(const TargetRegisterClass **, - SmallPtrSet&); - - bool createsNewJoin(LiveRange* LR, MachineBasicBlock* DefMBB, - MachineBasicBlock* BarrierMBB); - bool Rematerialize(unsigned vreg, VNInfo* ValNo, - MachineInstr* DefMI, - MachineBasicBlock::iterator RestorePt, - SmallPtrSet& RefsInMBB); - MachineInstr* FoldSpill(unsigned vreg, const TargetRegisterClass* RC, - MachineInstr* DefMI, - MachineInstr* Barrier, - MachineBasicBlock* MBB, - int& SS, - SmallPtrSet& RefsInMBB); - MachineInstr* FoldRestore(unsigned vreg, - const TargetRegisterClass* RC, - MachineInstr* Barrier, - MachineBasicBlock* MBB, - int SS, - SmallPtrSet& RefsInMBB); - void RenumberValno(VNInfo* VN); - void ReconstructLiveInterval(LiveInterval* LI); - bool removeDeadSpills(SmallPtrSet& split); - unsigned getNumberOfNonSpills(SmallPtrSet& MIs, - unsigned Reg, int FrameIndex, bool& TwoAddr); - VNInfo* PerformPHIConstruction(MachineBasicBlock::iterator Use, - MachineBasicBlock* MBB, LiveInterval* LI, - SmallPtrSet& Visited, - DenseMap >& Defs, - DenseMap >& Uses, - DenseMap& NewVNs, - DenseMap& LiveOut, - DenseMap& Phis, - bool IsTopLevel, bool IsIntraBlock); - VNInfo* PerformPHIConstructionFallBack(MachineBasicBlock::iterator Use, - MachineBasicBlock* MBB, LiveInterval* LI, - SmallPtrSet& Visited, - DenseMap >& Defs, - DenseMap >& Uses, - DenseMap& NewVNs, - DenseMap& LiveOut, - DenseMap& Phis, - bool IsTopLevel, bool IsIntraBlock); -}; -} // end anonymous namespace - -char PreAllocSplitting::ID = 0; - -INITIALIZE_PASS_BEGIN(PreAllocSplitting, "pre-alloc-splitting", - "Pre-Register Allocation Live Interval Splitting", - false, false) -INITIALIZE_PASS_DEPENDENCY(SlotIndexes) -INITIALIZE_PASS_DEPENDENCY(LiveIntervals) -INITIALIZE_PASS_DEPENDENCY(LiveStacks) -INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree) -INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo) -INITIALIZE_PASS_DEPENDENCY(VirtRegMap) -INITIALIZE_PASS_END(PreAllocSplitting, "pre-alloc-splitting", - "Pre-Register Allocation Live Interval Splitting", - false, false) - -char &llvm::PreAllocSplittingID = PreAllocSplitting::ID; - -/// findSpillPoint - Find a gap as far away from the given MI that's suitable -/// for spilling the current live interval. The index must be before any -/// defs and uses of the live interval register in the mbb. Return begin() if -/// none is found. -MachineBasicBlock::iterator -PreAllocSplitting::findSpillPoint(MachineBasicBlock *MBB, MachineInstr *MI, - MachineInstr *DefMI, - SmallPtrSet &RefsInMBB) { - MachineBasicBlock::iterator Pt = MBB->begin(); - - MachineBasicBlock::iterator MII = MI; - MachineBasicBlock::iterator EndPt = DefMI - ? MachineBasicBlock::iterator(DefMI) : MBB->begin(); - - while (MII != EndPt && !RefsInMBB.count(MII) && - MII->getOpcode() != TRI->getCallFrameSetupOpcode()) - --MII; - if (MII == EndPt || RefsInMBB.count(MII)) return Pt; - - while (MII != EndPt && !RefsInMBB.count(MII)) { - // We can't insert the spill between the barrier (a call), and its - // corresponding call frame setup. - if (MII->getOpcode() == TRI->getCallFrameDestroyOpcode()) { - while (MII->getOpcode() != TRI->getCallFrameSetupOpcode()) { - --MII; - if (MII == EndPt) { - return Pt; - } - } - continue; - } else { - Pt = MII; - } - - if (RefsInMBB.count(MII)) - return Pt; - - - --MII; - } - - return Pt; -} - -/// findRestorePoint - Find a gap in the instruction index map that's suitable -/// for restoring the current live interval value. The index must be before any -/// uses of the live interval register in the mbb. Return end() if none is -/// found. -MachineBasicBlock::iterator -PreAllocSplitting::findRestorePoint(MachineBasicBlock *MBB, MachineInstr *MI, - SlotIndex LastIdx, - SmallPtrSet &RefsInMBB) { - // FIXME: Allow spill to be inserted to the beginning of the mbb. Update mbb - // begin index accordingly. - MachineBasicBlock::iterator Pt = MBB->end(); - MachineBasicBlock::iterator EndPt = MBB->getFirstTerminator(); - - // We start at the call, so walk forward until we find the call frame teardown - // since we can't insert restores before that. Bail if we encounter a use - // during this time. - MachineBasicBlock::iterator MII = MI; - if (MII == EndPt) return Pt; - - while (MII != EndPt && !RefsInMBB.count(MII) && - MII->getOpcode() != TRI->getCallFrameDestroyOpcode()) - ++MII; - if (MII == EndPt || RefsInMBB.count(MII)) return Pt; - ++MII; - - // FIXME: Limit the number of instructions to examine to reduce - // compile time? - while (MII != EndPt) { - SlotIndex Index = LIs->getInstructionIndex(MII); - if (Index > LastIdx) - break; - - // We can't insert a restore between the barrier (a call) and its - // corresponding call frame teardown. - if (MII->getOpcode() == TRI->getCallFrameSetupOpcode()) { - do { - if (MII == EndPt || RefsInMBB.count(MII)) return Pt; - ++MII; - } while (MII->getOpcode() != TRI->getCallFrameDestroyOpcode()); - } else { - Pt = MII; - } - - if (RefsInMBB.count(MII)) - return Pt; - - ++MII; - } - - return Pt; -} - -/// CreateSpillStackSlot - Create a stack slot for the live interval being -/// split. If the live interval was previously split, just reuse the same -/// slot. -int PreAllocSplitting::CreateSpillStackSlot(unsigned Reg, - const TargetRegisterClass *RC) { - int SS; - DenseMap::iterator I = IntervalSSMap.find(Reg); - if (I != IntervalSSMap.end()) { - SS = I->second; - } else { - SS = MFI->CreateSpillStackObject(RC->getSize(), RC->getAlignment()); - IntervalSSMap[Reg] = SS; - } - - // Create live interval for stack slot. - CurrSLI = &LSs->getOrCreateInterval(SS, RC); - if (CurrSLI->hasAtLeastOneValue()) - CurrSValNo = CurrSLI->getValNumInfo(0); - else - CurrSValNo = CurrSLI->getNextValue(SlotIndex(), 0, - LSs->getVNInfoAllocator()); - return SS; -} - -/// IsAvailableInStack - Return true if register is available in a split stack -/// slot at the specified index. -bool -PreAllocSplitting::IsAvailableInStack(MachineBasicBlock *DefMBB, - unsigned Reg, SlotIndex DefIndex, - SlotIndex RestoreIndex, - SlotIndex &SpillIndex, - int& SS) const { - if (!DefMBB) - return false; - - DenseMap::const_iterator I = IntervalSSMap.find(Reg); - if (I == IntervalSSMap.end()) - return false; - DenseMap::const_iterator - II = Def2SpillMap.find(DefIndex); - if (II == Def2SpillMap.end()) - return false; - - // If last spill of def is in the same mbb as barrier mbb (where restore will - // be), make sure it's not below the intended restore index. - // FIXME: Undo the previous spill? - assert(LIs->getMBBFromIndex(II->second) == DefMBB); - if (DefMBB == BarrierMBB && II->second >= RestoreIndex) - return false; - - SS = I->second; - SpillIndex = II->second; - return true; -} - -/// UpdateSpillSlotInterval - Given the specified val# of the register live -/// interval being split, and the spill and restore indicies, update the live -/// interval of the spill stack slot. -void -PreAllocSplitting::UpdateSpillSlotInterval(VNInfo *ValNo, SlotIndex SpillIndex, - SlotIndex RestoreIndex) { - assert(LIs->getMBBFromIndex(RestoreIndex) == BarrierMBB && - "Expect restore in the barrier mbb"); - - MachineBasicBlock *MBB = LIs->getMBBFromIndex(SpillIndex); - if (MBB == BarrierMBB) { - // Intra-block spill + restore. We are done. - LiveRange SLR(SpillIndex, RestoreIndex, CurrSValNo); - CurrSLI->addRange(SLR); - return; - } - - SmallPtrSet Processed; - SlotIndex EndIdx = LIs->getMBBEndIdx(MBB); - LiveRange SLR(SpillIndex, EndIdx, CurrSValNo); - CurrSLI->addRange(SLR); - Processed.insert(MBB); - - // Start from the spill mbb, figure out the extend of the spill slot's - // live interval. - SmallVector WorkList; - const LiveRange *LR = CurrLI->getLiveRangeContaining(SpillIndex); - if (LR->end > EndIdx) - // If live range extend beyond end of mbb, add successors to work list. - for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(), - SE = MBB->succ_end(); SI != SE; ++SI) - WorkList.push_back(*SI); - - while (!WorkList.empty()) { - MachineBasicBlock *MBB = WorkList.back(); - WorkList.pop_back(); - if (Processed.count(MBB)) - continue; - SlotIndex Idx = LIs->getMBBStartIdx(MBB); - LR = CurrLI->getLiveRangeContaining(Idx); - if (LR && LR->valno == ValNo) { - EndIdx = LIs->getMBBEndIdx(MBB); - if (Idx <= RestoreIndex && RestoreIndex < EndIdx) { - // Spill slot live interval stops at the restore. - LiveRange SLR(Idx, RestoreIndex, CurrSValNo); - CurrSLI->addRange(SLR); - } else if (LR->end > EndIdx) { - // Live range extends beyond end of mbb, process successors. - LiveRange SLR(Idx, EndIdx.getNextIndex(), CurrSValNo); - CurrSLI->addRange(SLR); - for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(), - SE = MBB->succ_end(); SI != SE; ++SI) - WorkList.push_back(*SI); - } else { - LiveRange SLR(Idx, LR->end, CurrSValNo); - CurrSLI->addRange(SLR); - } - Processed.insert(MBB); - } - } -} - -/// PerformPHIConstruction - From properly set up use and def lists, use a PHI -/// construction algorithm to compute the ranges and valnos for an interval. -VNInfo* -PreAllocSplitting::PerformPHIConstruction(MachineBasicBlock::iterator UseI, - MachineBasicBlock* MBB, LiveInterval* LI, - SmallPtrSet& Visited, - DenseMap >& Defs, - DenseMap >& Uses, - DenseMap& NewVNs, - DenseMap& LiveOut, - DenseMap& Phis, - bool IsTopLevel, bool IsIntraBlock) { - // Return memoized result if it's available. - if (IsTopLevel && Visited.count(UseI) && NewVNs.count(UseI)) - return NewVNs[UseI]; - else if (!IsTopLevel && IsIntraBlock && NewVNs.count(UseI)) - return NewVNs[UseI]; - else if (!IsIntraBlock && LiveOut.count(MBB)) - return LiveOut[MBB]; - - // Check if our block contains any uses or defs. - bool ContainsDefs = Defs.count(MBB); - bool ContainsUses = Uses.count(MBB); - - VNInfo* RetVNI = 0; - - // Enumerate the cases of use/def contaning blocks. - if (!ContainsDefs && !ContainsUses) { - return PerformPHIConstructionFallBack(UseI, MBB, LI, Visited, Defs, Uses, - NewVNs, LiveOut, Phis, - IsTopLevel, IsIntraBlock); - } else if (ContainsDefs && !ContainsUses) { - SmallPtrSet& BlockDefs = Defs[MBB]; - - // Search for the def in this block. If we don't find it before the - // instruction we care about, go to the fallback case. Note that that - // should never happen: this cannot be intrablock, so use should - // always be an end() iterator. - assert(UseI == MBB->end() && "No use marked in intrablock"); - - MachineBasicBlock::iterator Walker = UseI; - --Walker; - while (Walker != MBB->begin()) { - if (BlockDefs.count(Walker)) - break; - --Walker; - } - - // Once we've found it, extend its VNInfo to our instruction. - SlotIndex DefIndex = LIs->getInstructionIndex(Walker); - DefIndex = DefIndex.getDefIndex(); - SlotIndex EndIndex = LIs->getMBBEndIdx(MBB); - - RetVNI = NewVNs[Walker]; - LI->addRange(LiveRange(DefIndex, EndIndex, RetVNI)); - } else if (!ContainsDefs && ContainsUses) { - SmallPtrSet& BlockUses = Uses[MBB]; - - // Search for the use in this block that precedes the instruction we care - // about, going to the fallback case if we don't find it. - MachineBasicBlock::iterator Walker = UseI; - bool found = false; - while (Walker != MBB->begin()) { - --Walker; - if (BlockUses.count(Walker)) { - found = true; - break; - } - } - - if (!found) - return PerformPHIConstructionFallBack(UseI, MBB, LI, Visited, Defs, - Uses, NewVNs, LiveOut, Phis, - IsTopLevel, IsIntraBlock); - - SlotIndex UseIndex = LIs->getInstructionIndex(Walker); - UseIndex = UseIndex.getUseIndex(); - SlotIndex EndIndex; - if (IsIntraBlock) { - EndIndex = LIs->getInstructionIndex(UseI).getDefIndex(); - } else - EndIndex = LIs->getMBBEndIdx(MBB); - - // Now, recursively phi construct the VNInfo for the use we found, - // and then extend it to include the instruction we care about - RetVNI = PerformPHIConstruction(Walker, MBB, LI, Visited, Defs, Uses, - NewVNs, LiveOut, Phis, false, true); - - LI->addRange(LiveRange(UseIndex, EndIndex, RetVNI)); - - // FIXME: Need to set kills properly for inter-block stuff. - } else if (ContainsDefs && ContainsUses) { - SmallPtrSet& BlockDefs = Defs[MBB]; - SmallPtrSet& BlockUses = Uses[MBB]; - - // This case is basically a merging of the two preceding case, with the - // special note that checking for defs must take precedence over checking - // for uses, because of two-address instructions. - MachineBasicBlock::iterator Walker = UseI; - bool foundDef = false; - bool foundUse = false; - while (Walker != MBB->begin()) { - --Walker; - if (BlockDefs.count(Walker)) { - foundDef = true; - break; - } else if (BlockUses.count(Walker)) { - foundUse = true; - break; - } - } - - if (!foundDef && !foundUse) - return PerformPHIConstructionFallBack(UseI, MBB, LI, Visited, Defs, - Uses, NewVNs, LiveOut, Phis, - IsTopLevel, IsIntraBlock); - - SlotIndex StartIndex = LIs->getInstructionIndex(Walker); - StartIndex = foundDef ? StartIndex.getDefIndex() : StartIndex.getUseIndex(); - SlotIndex EndIndex; - if (IsIntraBlock) { - EndIndex = LIs->getInstructionIndex(UseI).getDefIndex(); - } else - EndIndex = LIs->getMBBEndIdx(MBB); - - if (foundDef) - RetVNI = NewVNs[Walker]; - else - RetVNI = PerformPHIConstruction(Walker, MBB, LI, Visited, Defs, Uses, - NewVNs, LiveOut, Phis, false, true); - - LI->addRange(LiveRange(StartIndex, EndIndex, RetVNI)); - } - - // Memoize results so we don't have to recompute them. - if (!IsIntraBlock) LiveOut[MBB] = RetVNI; - else { - if (!NewVNs.count(UseI)) - NewVNs[UseI] = RetVNI; - Visited.insert(UseI); - } - - return RetVNI; -} - -/// PerformPHIConstructionFallBack - PerformPHIConstruction fall back path. -/// -VNInfo* -PreAllocSplitting::PerformPHIConstructionFallBack(MachineBasicBlock::iterator UseI, - MachineBasicBlock* MBB, LiveInterval* LI, - SmallPtrSet& Visited, - DenseMap >& Defs, - DenseMap >& Uses, - DenseMap& NewVNs, - DenseMap& LiveOut, - DenseMap& Phis, - bool IsTopLevel, bool IsIntraBlock) { - // NOTE: Because this is the fallback case from other cases, we do NOT - // assume that we are not intrablock here. - if (Phis.count(MBB)) return Phis[MBB]; - - SlotIndex StartIndex = LIs->getMBBStartIdx(MBB); - VNInfo *RetVNI = Phis[MBB] = - LI->getNextValue(SlotIndex(), /*FIXME*/ 0, - LIs->getVNInfoAllocator()); - - if (!IsIntraBlock) LiveOut[MBB] = RetVNI; - - // If there are no uses or defs between our starting point and the - // beginning of the block, then recursive perform phi construction - // on our predecessors. - DenseMap IncomingVNs; - for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(), - PE = MBB->pred_end(); PI != PE; ++PI) { - VNInfo* Incoming = PerformPHIConstruction((*PI)->end(), *PI, LI, - Visited, Defs, Uses, NewVNs, - LiveOut, Phis, false, false); - if (Incoming != 0) - IncomingVNs[*PI] = Incoming; - } - - if (MBB->pred_size() == 1 && !RetVNI->hasPHIKill()) { - VNInfo* OldVN = RetVNI; - VNInfo* NewVN = IncomingVNs.begin()->second; - VNInfo* MergedVN = LI->MergeValueNumberInto(OldVN, NewVN); - if (MergedVN == OldVN) std::swap(OldVN, NewVN); - - for (DenseMap::iterator LOI = LiveOut.begin(), - LOE = LiveOut.end(); LOI != LOE; ++LOI) - if (LOI->second == OldVN) - LOI->second = MergedVN; - for (DenseMap::iterator NVI = NewVNs.begin(), - NVE = NewVNs.end(); NVI != NVE; ++NVI) - if (NVI->second == OldVN) - NVI->second = MergedVN; - for (DenseMap::iterator PI = Phis.begin(), - PE = Phis.end(); PI != PE; ++PI) - if (PI->second == OldVN) - PI->second = MergedVN; - RetVNI = MergedVN; - } else { - // Otherwise, merge the incoming VNInfos with a phi join. Create a new - // VNInfo to represent the joined value. - for (DenseMap::iterator I = - IncomingVNs.begin(), E = IncomingVNs.end(); I != E; ++I) { - I->second->setHasPHIKill(true); - } - } - - SlotIndex EndIndex; - if (IsIntraBlock) { - EndIndex = LIs->getInstructionIndex(UseI).getDefIndex(); - } else - EndIndex = LIs->getMBBEndIdx(MBB); - LI->addRange(LiveRange(StartIndex, EndIndex, RetVNI)); - - // Memoize results so we don't have to recompute them. - if (!IsIntraBlock) - LiveOut[MBB] = RetVNI; - else { - if (!NewVNs.count(UseI)) - NewVNs[UseI] = RetVNI; - Visited.insert(UseI); - } - - return RetVNI; -} - -/// ReconstructLiveInterval - Recompute a live interval from scratch. -void PreAllocSplitting::ReconstructLiveInterval(LiveInterval* LI) { - VNInfo::Allocator& Alloc = LIs->getVNInfoAllocator(); - - // Clear the old ranges and valnos; - LI->clear(); - - // Cache the uses and defs of the register - typedef DenseMap > RegMap; - RegMap Defs, Uses; - - // Keep track of the new VNs we're creating. - DenseMap NewVNs; - SmallPtrSet PhiVNs; - - // Cache defs, and create a new VNInfo for each def. - for (MachineRegisterInfo::def_iterator DI = MRI->def_begin(LI->reg), - DE = MRI->def_end(); DI != DE; ++DI) { - Defs[(*DI).getParent()].insert(&*DI); - - SlotIndex DefIdx = LIs->getInstructionIndex(&*DI); - DefIdx = DefIdx.getDefIndex(); - - assert(!DI->isPHI() && "PHI instr in code during pre-alloc splitting."); - VNInfo* NewVN = LI->getNextValue(DefIdx, 0, Alloc); - - // If the def is a move, set the copy field. - if (DI->isCopyLike() && DI->getOperand(0).getReg() == LI->reg) - NewVN->setCopy(&*DI); - - NewVNs[&*DI] = NewVN; - } - - // Cache uses as a separate pass from actually processing them. - for (MachineRegisterInfo::use_iterator UI = MRI->use_begin(LI->reg), - UE = MRI->use_end(); UI != UE; ++UI) - Uses[(*UI).getParent()].insert(&*UI); - - // Now, actually process every use and use a phi construction algorithm - // to walk from it to its reaching definitions, building VNInfos along - // the way. - DenseMap LiveOut; - DenseMap Phis; - SmallPtrSet Visited; - for (MachineRegisterInfo::use_iterator UI = MRI->use_begin(LI->reg), - UE = MRI->use_end(); UI != UE; ++UI) { - PerformPHIConstruction(&*UI, UI->getParent(), LI, Visited, Defs, - Uses, NewVNs, LiveOut, Phis, true, true); - } - - // Add ranges for dead defs - for (MachineRegisterInfo::def_iterator DI = MRI->def_begin(LI->reg), - DE = MRI->def_end(); DI != DE; ++DI) { - SlotIndex DefIdx = LIs->getInstructionIndex(&*DI); - DefIdx = DefIdx.getDefIndex(); - - if (LI->liveAt(DefIdx)) continue; - - VNInfo* DeadVN = NewVNs[&*DI]; - LI->addRange(LiveRange(DefIdx, DefIdx.getNextSlot(), DeadVN)); - } -} - -/// RenumberValno - Split the given valno out into a new vreg, allowing it to -/// be allocated to a different register. This function creates a new vreg, -/// copies the valno and its live ranges over to the new vreg's interval, -/// removes them from the old interval, and rewrites all uses and defs of -/// the original reg to the new vreg within those ranges. -void PreAllocSplitting::RenumberValno(VNInfo* VN) { - SmallVector Stack; - SmallVector VNsToCopy; - Stack.push_back(VN); - - // Walk through and copy the valno we care about, and any other valnos - // that are two-address redefinitions of the one we care about. These - // will need to be rewritten as well. We also check for safety of the - // renumbering here, by making sure that none of the valno involved has - // phi kills. - while (!Stack.empty()) { - VNInfo* OldVN = Stack.back(); - Stack.pop_back(); - - // Bail out if we ever encounter a valno that has a PHI kill. We can't - // renumber these. - if (OldVN->hasPHIKill()) return; - - VNsToCopy.push_back(OldVN); - - // Locate two-address redefinitions - for (MachineRegisterInfo::def_iterator DI = MRI->def_begin(CurrLI->reg), - DE = MRI->def_end(); DI != DE; ++DI) { - if (!DI->isRegTiedToUseOperand(DI.getOperandNo())) continue; - SlotIndex DefIdx = LIs->getInstructionIndex(&*DI).getDefIndex(); - VNInfo* NextVN = CurrLI->findDefinedVNInfoForRegInt(DefIdx); - if (std::find(VNsToCopy.begin(), VNsToCopy.end(), NextVN) != - VNsToCopy.end()) - Stack.push_back(NextVN); - } - } - - // Create the new vreg - unsigned NewVReg = MRI->createVirtualRegister(MRI->getRegClass(CurrLI->reg)); - - // Create the new live interval - LiveInterval& NewLI = LIs->getOrCreateInterval(NewVReg); - - for (SmallVector::iterator OI = VNsToCopy.begin(), OE = - VNsToCopy.end(); OI != OE; ++OI) { - VNInfo* OldVN = *OI; - - // Copy the valno over - VNInfo* NewVN = NewLI.createValueCopy(OldVN, LIs->getVNInfoAllocator()); - NewLI.MergeValueInAsValue(*CurrLI, OldVN, NewVN); - - // Remove the valno from the old interval - CurrLI->removeValNo(OldVN); - } - - // Rewrite defs and uses. This is done in two stages to avoid invalidating - // the reg_iterator. - SmallVector, 8> OpsToChange; - - for (MachineRegisterInfo::reg_iterator I = MRI->reg_begin(CurrLI->reg), - E = MRI->reg_end(); I != E; ++I) { - MachineOperand& MO = I.getOperand(); - SlotIndex InstrIdx = LIs->getInstructionIndex(&*I); - - if ((MO.isUse() && NewLI.liveAt(InstrIdx.getUseIndex())) || - (MO.isDef() && NewLI.liveAt(InstrIdx.getDefIndex()))) - OpsToChange.push_back(std::make_pair(&*I, I.getOperandNo())); - } - - for (SmallVector, 8>::iterator I = - OpsToChange.begin(), E = OpsToChange.end(); I != E; ++I) { - MachineInstr* Inst = I->first; - unsigned OpIdx = I->second; - MachineOperand& MO = Inst->getOperand(OpIdx); - MO.setReg(NewVReg); - } - - // Grow the VirtRegMap, since we've created a new vreg. - VRM->grow(); - - // The renumbered vreg shares a stack slot with the old register. - if (IntervalSSMap.count(CurrLI->reg)) - IntervalSSMap[NewVReg] = IntervalSSMap[CurrLI->reg]; - - ++NumRenumbers; -} - -bool PreAllocSplitting::Rematerialize(unsigned VReg, VNInfo* ValNo, - MachineInstr* DefMI, - MachineBasicBlock::iterator RestorePt, - SmallPtrSet& RefsInMBB) { - MachineBasicBlock& MBB = *RestorePt->getParent(); - - MachineBasicBlock::iterator KillPt = BarrierMBB->end(); - if (!DefMI || DefMI->getParent() == BarrierMBB) - KillPt = findSpillPoint(BarrierMBB, Barrier, NULL, RefsInMBB); - else - KillPt = llvm::next(MachineBasicBlock::iterator(DefMI)); - - if (KillPt == DefMI->getParent()->end()) - return false; - - TII->reMaterialize(MBB, RestorePt, VReg, 0, DefMI, *TRI); - SlotIndex RematIdx = LIs->InsertMachineInstrInMaps(prior(RestorePt)); - - ReconstructLiveInterval(CurrLI); - RematIdx = RematIdx.getDefIndex(); - RenumberValno(CurrLI->findDefinedVNInfoForRegInt(RematIdx)); - - ++NumSplits; - ++NumRemats; - return true; -} - -MachineInstr* PreAllocSplitting::FoldSpill(unsigned vreg, - const TargetRegisterClass* RC, - MachineInstr* DefMI, - MachineInstr* Barrier, - MachineBasicBlock* MBB, - int& SS, - SmallPtrSet& RefsInMBB) { - // Go top down if RefsInMBB is empty. - if (RefsInMBB.empty()) - return 0; - - MachineBasicBlock::iterator FoldPt = Barrier; - while (&*FoldPt != DefMI && FoldPt != MBB->begin() && - !RefsInMBB.count(FoldPt)) - --FoldPt; - - int OpIdx = FoldPt->findRegisterDefOperandIdx(vreg); - if (OpIdx == -1) - return 0; - - SmallVector Ops; - Ops.push_back(OpIdx); - - if (!TII->canFoldMemoryOperand(FoldPt, Ops)) - return 0; - - DenseMap::iterator I = IntervalSSMap.find(vreg); - if (I != IntervalSSMap.end()) { - SS = I->second; - } else { - SS = MFI->CreateSpillStackObject(RC->getSize(), RC->getAlignment()); - } - - MachineInstr* FMI = TII->foldMemoryOperand(FoldPt, Ops, SS); - - if (FMI) { - LIs->ReplaceMachineInstrInMaps(FoldPt, FMI); - FoldPt->eraseFromParent(); - ++NumFolds; - - IntervalSSMap[vreg] = SS; - CurrSLI = &LSs->getOrCreateInterval(SS, RC); - if (CurrSLI->hasAtLeastOneValue()) - CurrSValNo = CurrSLI->getValNumInfo(0); - else - CurrSValNo = CurrSLI->getNextValue(SlotIndex(), 0, - LSs->getVNInfoAllocator()); - } - - return FMI; -} - -MachineInstr* PreAllocSplitting::FoldRestore(unsigned vreg, - const TargetRegisterClass* RC, - MachineInstr* Barrier, - MachineBasicBlock* MBB, - int SS, - SmallPtrSet& RefsInMBB) { - if ((int)RestoreFoldLimit != -1 && RestoreFoldLimit == (int)NumRestoreFolds) - return 0; - - // Go top down if RefsInMBB is empty. - if (RefsInMBB.empty()) - return 0; - - // Can't fold a restore between a call stack setup and teardown. - MachineBasicBlock::iterator FoldPt = Barrier; - - // Advance from barrier to call frame teardown. - while (FoldPt != MBB->getFirstTerminator() && - FoldPt->getOpcode() != TRI->getCallFrameDestroyOpcode()) { - if (RefsInMBB.count(FoldPt)) - return 0; - - ++FoldPt; - } - - if (FoldPt == MBB->getFirstTerminator()) - return 0; - else - ++FoldPt; - - // Now find the restore point. - while (FoldPt != MBB->getFirstTerminator() && !RefsInMBB.count(FoldPt)) { - if (FoldPt->getOpcode() == TRI->getCallFrameSetupOpcode()) { - while (FoldPt != MBB->getFirstTerminator() && - FoldPt->getOpcode() != TRI->getCallFrameDestroyOpcode()) { - if (RefsInMBB.count(FoldPt)) - return 0; - - ++FoldPt; - } - - if (FoldPt == MBB->getFirstTerminator()) - return 0; - } - - ++FoldPt; - } - - if (FoldPt == MBB->getFirstTerminator()) - return 0; - - int OpIdx = FoldPt->findRegisterUseOperandIdx(vreg, true); - if (OpIdx == -1) - return 0; - - SmallVector Ops; - Ops.push_back(OpIdx); - - if (!TII->canFoldMemoryOperand(FoldPt, Ops)) - return 0; - - MachineInstr* FMI = TII->foldMemoryOperand(FoldPt, Ops, SS); - - if (FMI) { - LIs->ReplaceMachineInstrInMaps(FoldPt, FMI); - FoldPt->eraseFromParent(); - ++NumRestoreFolds; - } - - return FMI; -} - -/// SplitRegLiveInterval - Split (spill and restore) the given live interval -/// so it would not cross the barrier that's being processed. Shrink wrap -/// (minimize) the live interval to the last uses. -bool PreAllocSplitting::SplitRegLiveInterval(LiveInterval *LI) { - DEBUG(dbgs() << "Pre-alloc splitting " << LI->reg << " for " << *Barrier - << " result: "); - - CurrLI = LI; - - // Find live range where current interval cross the barrier. - LiveInterval::iterator LR = - CurrLI->FindLiveRangeContaining(BarrierIdx.getUseIndex()); - VNInfo *ValNo = LR->valno; - - assert(!ValNo->isUnused() && "Val# is defined by a dead def?"); - - MachineInstr *DefMI = LIs->getInstructionFromIndex(ValNo->def); - - // If this would create a new join point, do not split. - if (DefMI && createsNewJoin(LR, DefMI->getParent(), Barrier->getParent())) { - DEBUG(dbgs() << "FAILED (would create a new join point).\n"); - return false; - } - - // Find all references in the barrier mbb. - SmallPtrSet RefsInMBB; - for (MachineRegisterInfo::reg_iterator I = MRI->reg_begin(CurrLI->reg), - E = MRI->reg_end(); I != E; ++I) { - MachineInstr *RefMI = &*I; - if (RefMI->getParent() == BarrierMBB) - RefsInMBB.insert(RefMI); - } - - // Find a point to restore the value after the barrier. - MachineBasicBlock::iterator RestorePt = - findRestorePoint(BarrierMBB, Barrier, LR->end, RefsInMBB); - if (RestorePt == BarrierMBB->end()) { - DEBUG(dbgs() << "FAILED (could not find a suitable restore point).\n"); - return false; - } - - if (DefMI && LIs->isReMaterializable(*LI, ValNo, DefMI)) - if (Rematerialize(LI->reg, ValNo, DefMI, RestorePt, RefsInMBB)) { - DEBUG(dbgs() << "success (remat).\n"); - return true; - } - - // Add a spill either before the barrier or after the definition. - MachineBasicBlock *DefMBB = DefMI ? DefMI->getParent() : NULL; - const TargetRegisterClass *RC = MRI->getRegClass(CurrLI->reg); - SlotIndex SpillIndex; - MachineInstr *SpillMI = NULL; - int SS = -1; - if (!DefMI) { - // If we don't know where the def is we must split just before the barrier. - if ((SpillMI = FoldSpill(LI->reg, RC, 0, Barrier, - BarrierMBB, SS, RefsInMBB))) { - SpillIndex = LIs->getInstructionIndex(SpillMI); - } else { - MachineBasicBlock::iterator SpillPt = - findSpillPoint(BarrierMBB, Barrier, NULL, RefsInMBB); - if (SpillPt == BarrierMBB->begin()) { - DEBUG(dbgs() << "FAILED (could not find a suitable spill point).\n"); - return false; // No gap to insert spill. - } - // Add spill. - - SS = CreateSpillStackSlot(CurrLI->reg, RC); - TII->storeRegToStackSlot(*BarrierMBB, SpillPt, CurrLI->reg, true, SS, RC, - TRI); - SpillMI = prior(SpillPt); - SpillIndex = LIs->InsertMachineInstrInMaps(SpillMI); - } - } else if (!IsAvailableInStack(DefMBB, CurrLI->reg, ValNo->def, - LIs->getZeroIndex(), SpillIndex, SS)) { - // If it's already split, just restore the value. There is no need to spill - // the def again. - if (!DefMI) { - DEBUG(dbgs() << "FAILED (def is dead).\n"); - return false; // Def is dead. Do nothing. - } - - if ((SpillMI = FoldSpill(LI->reg, RC, DefMI, Barrier, - BarrierMBB, SS, RefsInMBB))) { - SpillIndex = LIs->getInstructionIndex(SpillMI); - } else { - // Check if it's possible to insert a spill after the def MI. - MachineBasicBlock::iterator SpillPt; - if (DefMBB == BarrierMBB) { - // Add spill after the def and the last use before the barrier. - SpillPt = findSpillPoint(BarrierMBB, Barrier, DefMI, - RefsInMBB); - if (SpillPt == DefMBB->begin()) { - DEBUG(dbgs() << "FAILED (could not find a suitable spill point).\n"); - return false; // No gap to insert spill. - } - } else { - SpillPt = llvm::next(MachineBasicBlock::iterator(DefMI)); - if (SpillPt == DefMBB->end()) { - DEBUG(dbgs() << "FAILED (could not find a suitable spill point).\n"); - return false; // No gap to insert spill. - } - } - // Add spill. - SS = CreateSpillStackSlot(CurrLI->reg, RC); - TII->storeRegToStackSlot(*DefMBB, SpillPt, CurrLI->reg, false, SS, RC, - TRI); - SpillMI = prior(SpillPt); - SpillIndex = LIs->InsertMachineInstrInMaps(SpillMI); - } - } - - // Remember def instruction index to spill index mapping. - if (DefMI && SpillMI) - Def2SpillMap[ValNo->def] = SpillIndex; - - // Add restore. - bool FoldedRestore = false; - SlotIndex RestoreIndex; - if (MachineInstr* LMI = FoldRestore(CurrLI->reg, RC, Barrier, - BarrierMBB, SS, RefsInMBB)) { - RestorePt = LMI; - RestoreIndex = LIs->getInstructionIndex(RestorePt); - FoldedRestore = true; - } else { - TII->loadRegFromStackSlot(*BarrierMBB, RestorePt, CurrLI->reg, SS, RC, TRI); - MachineInstr *LoadMI = prior(RestorePt); - RestoreIndex = LIs->InsertMachineInstrInMaps(LoadMI); - } - - // Update spill stack slot live interval. - UpdateSpillSlotInterval(ValNo, SpillIndex.getUseIndex().getNextSlot(), - RestoreIndex.getDefIndex()); - - ReconstructLiveInterval(CurrLI); - - if (!FoldedRestore) { - SlotIndex RestoreIdx = LIs->getInstructionIndex(prior(RestorePt)); - RestoreIdx = RestoreIdx.getDefIndex(); - RenumberValno(CurrLI->findDefinedVNInfoForRegInt(RestoreIdx)); - } - - ++NumSplits; - DEBUG(dbgs() << "success.\n"); - return true; -} - -/// SplitRegLiveIntervals - Split all register live intervals that cross the -/// barrier that's being processed. -bool -PreAllocSplitting::SplitRegLiveIntervals(const TargetRegisterClass **RCs, - SmallPtrSet& Split) { - // First find all the virtual registers whose live intervals are intercepted - // by the current barrier. - SmallVector Intervals; - for (const TargetRegisterClass **RC = RCs; *RC; ++RC) { - // FIXME: If it's not safe to move any instruction that defines the barrier - // register class, then it means there are some special dependencies which - // codegen is not modelling. Ignore these barriers for now. - if (!TII->isSafeToMoveRegClassDefs(*RC)) - continue; - const std::vector &VRs = MRI->getRegClassVirtRegs(*RC); - for (unsigned i = 0, e = VRs.size(); i != e; ++i) { - unsigned Reg = VRs[i]; - if (!LIs->hasInterval(Reg)) - continue; - LiveInterval *LI = &LIs->getInterval(Reg); - if (LI->liveAt(BarrierIdx) && !Barrier->readsRegister(Reg)) - // Virtual register live interval is intercepted by the barrier. We - // should split and shrink wrap its interval if possible. - Intervals.push_back(LI); - } - } - - // Process the affected live intervals. - bool Change = false; - while (!Intervals.empty()) { - if (PreSplitLimit != -1 && (int)NumSplits == PreSplitLimit) - break; - LiveInterval *LI = Intervals.back(); - Intervals.pop_back(); - bool result = SplitRegLiveInterval(LI); - if (result) Split.insert(LI); - Change |= result; - } - - return Change; -} - -unsigned PreAllocSplitting::getNumberOfNonSpills( - SmallPtrSet& MIs, - unsigned Reg, int FrameIndex, - bool& FeedsTwoAddr) { - unsigned NonSpills = 0; - for (SmallPtrSet::iterator UI = MIs.begin(), UE = MIs.end(); - UI != UE; ++UI) { - int StoreFrameIndex; - unsigned StoreVReg = TII->isStoreToStackSlot(*UI, StoreFrameIndex); - if (StoreVReg != Reg || StoreFrameIndex != FrameIndex) - ++NonSpills; - - int DefIdx = (*UI)->findRegisterDefOperandIdx(Reg); - if (DefIdx != -1 && (*UI)->isRegTiedToUseOperand(DefIdx)) - FeedsTwoAddr = true; - } - - return NonSpills; -} - -/// removeDeadSpills - After doing splitting, filter through all intervals we've -/// split, and see if any of the spills are unnecessary. If so, remove them. -bool PreAllocSplitting::removeDeadSpills(SmallPtrSet& split) { - bool changed = false; - - // Walk over all of the live intervals that were touched by the splitter, - // and see if we can do any DCE and/or folding. - for (SmallPtrSet::iterator LI = split.begin(), - LE = split.end(); LI != LE; ++LI) { - DenseMap > VNUseCount; - - // First, collect all the uses of the vreg, and sort them by their - // reaching definition (VNInfo). - for (MachineRegisterInfo::use_iterator UI = MRI->use_begin((*LI)->reg), - UE = MRI->use_end(); UI != UE; ++UI) { - SlotIndex index = LIs->getInstructionIndex(&*UI); - index = index.getUseIndex(); - - const LiveRange* LR = (*LI)->getLiveRangeContaining(index); - VNUseCount[LR->valno].insert(&*UI); - } - - // Now, take the definitions (VNInfo's) one at a time and try to DCE - // and/or fold them away. - for (LiveInterval::vni_iterator VI = (*LI)->vni_begin(), - VE = (*LI)->vni_end(); VI != VE; ++VI) { - - if (DeadSplitLimit != -1 && (int)NumDeadSpills == DeadSplitLimit) - return changed; - - VNInfo* CurrVN = *VI; - - // We don't currently try to handle definitions with PHI kills, because - // it would involve processing more than one VNInfo at once. - if (CurrVN->hasPHIKill()) continue; - - // We also don't try to handle the results of PHI joins, since there's - // no defining instruction to analyze. - MachineInstr* DefMI = LIs->getInstructionFromIndex(CurrVN->def); - if (!DefMI || CurrVN->isUnused()) continue; - - // We're only interested in eliminating cruft introduced by the splitter, - // is of the form load-use or load-use-store. First, check that the - // definition is a load, and remember what stack slot we loaded it from. - int FrameIndex; - if (!TII->isLoadFromStackSlot(DefMI, FrameIndex)) continue; - - // If the definition has no uses at all, just DCE it. - if (VNUseCount[CurrVN].size() == 0) { - LIs->RemoveMachineInstrFromMaps(DefMI); - (*LI)->removeValNo(CurrVN); - DefMI->eraseFromParent(); - VNUseCount.erase(CurrVN); - ++NumDeadSpills; - changed = true; - continue; - } - - // Second, get the number of non-store uses of the definition, as well as - // a flag indicating whether it feeds into a later two-address definition. - bool FeedsTwoAddr = false; - unsigned NonSpillCount = getNumberOfNonSpills(VNUseCount[CurrVN], - (*LI)->reg, FrameIndex, - FeedsTwoAddr); - - // If there's one non-store use and it doesn't feed a two-addr, then - // this is a load-use-store case that we can try to fold. - if (NonSpillCount == 1 && !FeedsTwoAddr) { - // Start by finding the non-store use MachineInstr. - SmallPtrSet::iterator UI = VNUseCount[CurrVN].begin(); - int StoreFrameIndex; - unsigned StoreVReg = TII->isStoreToStackSlot(*UI, StoreFrameIndex); - while (UI != VNUseCount[CurrVN].end() && - (StoreVReg == (*LI)->reg && StoreFrameIndex == FrameIndex)) { - ++UI; - if (UI != VNUseCount[CurrVN].end()) - StoreVReg = TII->isStoreToStackSlot(*UI, StoreFrameIndex); - } - if (UI == VNUseCount[CurrVN].end()) continue; - - MachineInstr* use = *UI; - - // Attempt to fold it away! - int OpIdx = use->findRegisterUseOperandIdx((*LI)->reg, false); - if (OpIdx == -1) continue; - SmallVector Ops; - Ops.push_back(OpIdx); - if (!TII->canFoldMemoryOperand(use, Ops)) continue; - - MachineInstr* NewMI = TII->foldMemoryOperand(use, Ops, FrameIndex); - - if (!NewMI) continue; - - // Update relevant analyses. - LIs->RemoveMachineInstrFromMaps(DefMI); - LIs->ReplaceMachineInstrInMaps(use, NewMI); - (*LI)->removeValNo(CurrVN); - - DefMI->eraseFromParent(); - use->eraseFromParent(); - VNUseCount[CurrVN].erase(use); - - // Remove deleted instructions. Note that we need to remove them from - // the VNInfo->use map as well, just to be safe. - for (SmallPtrSet::iterator II = - VNUseCount[CurrVN].begin(), IE = VNUseCount[CurrVN].end(); - II != IE; ++II) { - for (DenseMap >::iterator - VNI = VNUseCount.begin(), VNE = VNUseCount.end(); VNI != VNE; - ++VNI) - if (VNI->first != CurrVN) - VNI->second.erase(*II); - LIs->RemoveMachineInstrFromMaps(*II); - (*II)->eraseFromParent(); - } - - VNUseCount.erase(CurrVN); - - for (DenseMap >::iterator - VI = VNUseCount.begin(), VE = VNUseCount.end(); VI != VE; ++VI) - if (VI->second.erase(use)) - VI->second.insert(NewMI); - - ++NumDeadSpills; - changed = true; - continue; - } - - // If there's more than one non-store instruction, we can't profitably - // fold it, so bail. - if (NonSpillCount) continue; - - // Otherwise, this is a load-store case, so DCE them. - for (SmallPtrSet::iterator UI = - VNUseCount[CurrVN].begin(), UE = VNUseCount[CurrVN].end(); - UI != UE; ++UI) { - LIs->RemoveMachineInstrFromMaps(*UI); - (*UI)->eraseFromParent(); - } - - VNUseCount.erase(CurrVN); - - LIs->RemoveMachineInstrFromMaps(DefMI); - (*LI)->removeValNo(CurrVN); - DefMI->eraseFromParent(); - ++NumDeadSpills; - changed = true; - } - } - - return changed; -} - -bool PreAllocSplitting::createsNewJoin(LiveRange* LR, - MachineBasicBlock* DefMBB, - MachineBasicBlock* BarrierMBB) { - if (DefMBB == BarrierMBB) - return false; - - if (LR->valno->hasPHIKill()) - return false; - - SlotIndex MBBEnd = LIs->getMBBEndIdx(BarrierMBB); - if (LR->end < MBBEnd) - return false; - - MachineLoopInfo& MLI = getAnalysis(); - if (MLI.getLoopFor(DefMBB) != MLI.getLoopFor(BarrierMBB)) - return true; - - MachineDominatorTree& MDT = getAnalysis(); - SmallPtrSet Visited; - typedef std::pair ItPair; - SmallVector Stack; - Stack.push_back(std::make_pair(BarrierMBB, BarrierMBB->succ_begin())); - - while (!Stack.empty()) { - ItPair P = Stack.back(); - Stack.pop_back(); - - MachineBasicBlock* PredMBB = P.first; - MachineBasicBlock::succ_iterator S = P.second; - - if (S == PredMBB->succ_end()) - continue; - else if (Visited.count(*S)) { - Stack.push_back(std::make_pair(PredMBB, ++S)); - continue; - } else - Stack.push_back(std::make_pair(PredMBB, S+1)); - - MachineBasicBlock* MBB = *S; - Visited.insert(MBB); - - if (MBB == BarrierMBB) - return true; - - MachineDomTreeNode* DefMDTN = MDT.getNode(DefMBB); - MachineDomTreeNode* BarrierMDTN = MDT.getNode(BarrierMBB); - MachineDomTreeNode* MDTN = MDT.getNode(MBB)->getIDom(); - while (MDTN) { - if (MDTN == DefMDTN) - return true; - else if (MDTN == BarrierMDTN) - break; - MDTN = MDTN->getIDom(); - } - - MBBEnd = LIs->getMBBEndIdx(MBB); - if (LR->end > MBBEnd) - Stack.push_back(std::make_pair(MBB, MBB->succ_begin())); - } - - return false; -} - - -bool PreAllocSplitting::runOnMachineFunction(MachineFunction &MF) { - CurrMF = &MF; - TM = &MF.getTarget(); - TRI = TM->getRegisterInfo(); - TII = TM->getInstrInfo(); - MFI = MF.getFrameInfo(); - MRI = &MF.getRegInfo(); - SIs = &getAnalysis(); - LIs = &getAnalysis(); - LSs = &getAnalysis(); - VRM = &getAnalysis(); - - bool MadeChange = false; - - // Make sure blocks are numbered in order. - MF.RenumberBlocks(); - - MachineBasicBlock *Entry = MF.begin(); - SmallPtrSet Visited; - - SmallPtrSet Split; - - for (df_ext_iterator > - DFI = df_ext_begin(Entry, Visited), E = df_ext_end(Entry, Visited); - DFI != E; ++DFI) { - BarrierMBB = *DFI; - for (MachineBasicBlock::iterator I = BarrierMBB->begin(), - E = BarrierMBB->end(); I != E; ++I) { - Barrier = &*I; - const TargetRegisterClass **BarrierRCs = - Barrier->getDesc().getRegClassBarriers(); - if (!BarrierRCs) - continue; - BarrierIdx = LIs->getInstructionIndex(Barrier); - MadeChange |= SplitRegLiveIntervals(BarrierRCs, Split); - } - } - - MadeChange |= removeDeadSpills(Split); - - return MadeChange; -} diff --git a/lib/CodeGen/RegAllocLinearScan.cpp b/lib/CodeGen/RegAllocLinearScan.cpp index 2ad0747..0dd3c59 100644 --- a/lib/CodeGen/RegAllocLinearScan.cpp +++ b/lib/CodeGen/RegAllocLinearScan.cpp @@ -58,11 +58,6 @@ NewHeuristic("new-spilling-heuristic", cl::init(false), cl::Hidden); static cl::opt -PreSplitIntervals("pre-alloc-split", - cl::desc("Pre-register allocation live interval splitting"), - cl::init(false), cl::Hidden); - -static cl::opt TrivCoalesceEnds("trivial-coalesce-ends", cl::desc("Attempt trivial coalescing of interval ends"), cl::init(false), cl::Hidden); @@ -104,7 +99,6 @@ namespace { initializeRegisterCoalescerPass( *PassRegistry::getPassRegistry()); initializeCalculateSpillWeightsPass(*PassRegistry::getPassRegistry()); - initializePreAllocSplittingPass(*PassRegistry::getPassRegistry()); initializeLiveStacksPass(*PassRegistry::getPassRegistry()); initializeMachineDominatorTreePass(*PassRegistry::getPassRegistry()); initializeMachineLoopInfoPass(*PassRegistry::getPassRegistry()); @@ -217,8 +211,6 @@ namespace { // to coalescing and which analyses coalescing invalidates. AU.addRequiredTransitive(); AU.addRequired(); - if (PreSplitIntervals) - AU.addRequiredID(PreAllocSplittingID); AU.addRequiredID(LiveStacksID); AU.addPreservedID(LiveStacksID); AU.addRequired(); @@ -401,7 +393,6 @@ INITIALIZE_PASS_BEGIN(RALinScan, "linearscan-regalloc", INITIALIZE_PASS_DEPENDENCY(LiveIntervals) INITIALIZE_PASS_DEPENDENCY(StrongPHIElimination) INITIALIZE_PASS_DEPENDENCY(CalculateSpillWeights) -INITIALIZE_PASS_DEPENDENCY(PreAllocSplitting) INITIALIZE_PASS_DEPENDENCY(LiveStacks) INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo) INITIALIZE_PASS_DEPENDENCY(VirtRegMap) diff --git a/test/CodeGen/X86/pre-split1.ll b/test/CodeGen/X86/pre-split1.ll deleted file mode 100644 index b55bf57..0000000 --- a/test/CodeGen/X86/pre-split1.ll +++ /dev/null @@ -1,24 +0,0 @@ -; RUN: llc < %s -march=x86 -mattr=+sse2 -pre-alloc-split -regalloc=linearscan -stats |& \ -; RUN: grep {pre-alloc-split} | grep {Number of intervals split} | grep 1 -; XFAIL: * - -define void @test(double* %P, i32 %cond) nounwind { -entry: - %0 = load double* %P, align 8 ; [#uses=1] - %1 = fadd double %0, 4.000000e+00 ; [#uses=2] - %2 = icmp eq i32 %cond, 0 ; [#uses=1] - br i1 %2, label %bb1, label %bb - -bb: ; preds = %entry - %3 = fadd double %1, 4.000000e+00 ; [#uses=1] - br label %bb1 - -bb1: ; preds = %bb, %entry - %A.0 = phi double [ %3, %bb ], [ %1, %entry ] ; [#uses=1] - %4 = fmul double %A.0, 4.000000e+00 ; [#uses=1] - %5 = tail call i32 (...)* @bar() nounwind ; [#uses=0] - store double %4, double* %P, align 8 - ret void -} - -declare i32 @bar(...) diff --git a/test/CodeGen/X86/pre-split10.ll b/test/CodeGen/X86/pre-split10.ll deleted file mode 100644 index 83c6450..0000000 --- a/test/CodeGen/X86/pre-split10.ll +++ /dev/null @@ -1,51 +0,0 @@ -; RUN: llc < %s -march=x86 -mattr=+sse2 -pre-alloc-split -regalloc=linearscan - -define i32 @main(i32 %argc, i8** %argv) nounwind { -entry: - br label %bb14.i - -bb14.i: ; preds = %bb14.i, %entry - %i8.0.reg2mem.0.i = phi i32 [ 0, %entry ], [ %0, %bb14.i ] ; [#uses=1] - %0 = add i32 %i8.0.reg2mem.0.i, 1 ; [#uses=2] - %1 = fadd double 0.000000e+00, 0.000000e+00 ; [#uses=1] - %2 = fadd double 0.000000e+00, 0.000000e+00 ; [#uses=1] - %3 = fadd double 0.000000e+00, 0.000000e+00 ; [#uses=1] - %exitcond75.i = icmp eq i32 %0, 32 ; [#uses=1] - br i1 %exitcond75.i, label %bb24.i, label %bb14.i - -bb24.i: ; preds = %bb14.i - %4 = fdiv double 0.000000e+00, 0.000000e+00 ; [#uses=1] - %5 = fdiv double %1, 0.000000e+00 ; [#uses=1] - %6 = fdiv double %2, 0.000000e+00 ; [#uses=1] - %7 = fdiv double %3, 0.000000e+00 ; [#uses=1] - br label %bb31.i - -bb31.i: ; preds = %bb31.i, %bb24.i - %tmp.0.reg2mem.0.i = phi i32 [ 0, %bb24.i ], [ %indvar.next64.i, %bb31.i ] ; [#uses=1] - %indvar.next64.i = add i32 %tmp.0.reg2mem.0.i, 1 ; [#uses=2] - %exitcond65.i = icmp eq i32 %indvar.next64.i, 64 ; [#uses=1] - br i1 %exitcond65.i, label %bb33.i, label %bb31.i - -bb33.i: ; preds = %bb31.i - br label %bb35.preheader.i - -bb5.i.i: ; preds = %bb35.preheader.i - %8 = call double @floor(double 0.000000e+00) nounwind readnone ; [#uses=0] - br label %bb7.i.i - -bb7.i.i: ; preds = %bb35.preheader.i, %bb5.i.i - br label %bb35.preheader.i - -bb35.preheader.i: ; preds = %bb7.i.i, %bb33.i - %9 = fsub double 0.000000e+00, %4 ; [#uses=1] - store double %9, double* null, align 8 - %10 = fsub double 0.000000e+00, %5 ; [#uses=1] - store double %10, double* null, align 8 - %11 = fsub double 0.000000e+00, %6 ; [#uses=1] - store double %11, double* null, align 8 - %12 = fsub double 0.000000e+00, %7 ; [#uses=1] - store double %12, double* null, align 8 - br i1 false, label %bb7.i.i, label %bb5.i.i -} - -declare double @floor(double) nounwind readnone diff --git a/test/CodeGen/X86/pre-split11.ll b/test/CodeGen/X86/pre-split11.ll deleted file mode 100644 index 3d549f9..0000000 --- a/test/CodeGen/X86/pre-split11.ll +++ /dev/null @@ -1,34 +0,0 @@ -; RUN: llc < %s -mtriple=x86_64-apple-darwin -mattr=+sse2 -pre-alloc-split -regalloc=linearscan | FileCheck %s - -@.str = private constant [28 x i8] c"\0A\0ADOUBLE D = %f\0A\00", align 1 ; <[28 x i8]*> [#uses=1] -@.str1 = private constant [37 x i8] c"double to long l1 = %ld\09\09(0x%lx)\0A\00", align 8 ; <[37 x i8]*> [#uses=1] -@.str2 = private constant [35 x i8] c"double to uint ui1 = %u\09\09(0x%x)\0A\00", align 8 ; <[35 x i8]*> [#uses=1] -@.str3 = private constant [37 x i8] c"double to ulong ul1 = %lu\09\09(0x%lx)\0A\00", align 8 ; <[37 x i8]*> [#uses=1] - -define i32 @main(i32 %argc, i8** nocapture %argv) nounwind ssp { -; CHECK: movsd %xmm0, (%rsp) -entry: - %0 = icmp sgt i32 %argc, 4 ; [#uses=1] - br i1 %0, label %bb, label %bb2 - -bb: ; preds = %entry - %1 = getelementptr inbounds i8** %argv, i64 4 ; [#uses=1] - %2 = load i8** %1, align 8 ; [#uses=1] - %3 = tail call double @atof(i8* %2) nounwind ; [#uses=1] - br label %bb2 - -bb2: ; preds = %bb, %entry - %storemerge = phi double [ %3, %bb ], [ 2.000000e+00, %entry ] ; [#uses=4] - %4 = fptoui double %storemerge to i32 ; [#uses=2] - %5 = fptoui double %storemerge to i64 ; [#uses=2] - %6 = fptosi double %storemerge to i64 ; [#uses=2] - %7 = tail call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([28 x i8]* @.str, i64 0, i64 0), double %storemerge) nounwind ; [#uses=0] - %8 = tail call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([37 x i8]* @.str1, i64 0, i64 0), i64 %6, i64 %6) nounwind ; [#uses=0] - %9 = tail call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([35 x i8]* @.str2, i64 0, i64 0), i32 %4, i32 %4) nounwind ; [#uses=0] - %10 = tail call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([37 x i8]* @.str3, i64 0, i64 0), i64 %5, i64 %5) nounwind ; [#uses=0] - ret i32 0 -} - -declare double @atof(i8* nocapture) nounwind readonly - -declare i32 @printf(i8* nocapture, ...) nounwind diff --git a/test/CodeGen/X86/pre-split4.ll b/test/CodeGen/X86/pre-split4.ll deleted file mode 100644 index 37d1ac6..0000000 --- a/test/CodeGen/X86/pre-split4.ll +++ /dev/null @@ -1,26 +0,0 @@ -; RUN: llc < %s -march=x86 -mattr=+sse2 -pre-alloc-split -regalloc=linearscan -stats |& \ -; RUN: grep {pre-alloc-split} | grep {Number of intervals split} | grep 2 - -define i32 @main(i32 %argc, i8** %argv) nounwind { -entry: - br label %bb - -bb: ; preds = %bb, %entry - %k.0.reg2mem.0 = phi double [ 1.000000e+00, %entry ], [ %6, %bb ] ; [#uses=2] - %Flint.0.reg2mem.0 = phi double [ 0.000000e+00, %entry ], [ %5, %bb ] ; [#uses=1] - %twoThrd.0.reg2mem.0 = phi double [ 0.000000e+00, %entry ], [ %1, %bb ] ; [#uses=1] - %0 = tail call double @llvm.pow.f64(double 0x3FE5555555555555, double 0.000000e+00) ; [#uses=1] - %1 = fadd double %0, %twoThrd.0.reg2mem.0 ; [#uses=1] - %2 = tail call double @sin(double %k.0.reg2mem.0) nounwind readonly ; [#uses=1] - %3 = fmul double 0.000000e+00, %2 ; [#uses=1] - %4 = fdiv double 1.000000e+00, %3 ; [#uses=1] - store double %Flint.0.reg2mem.0, double* null - store double %twoThrd.0.reg2mem.0, double* null - %5 = fadd double %4, %Flint.0.reg2mem.0 ; [#uses=1] - %6 = fadd double %k.0.reg2mem.0, 1.000000e+00 ; [#uses=1] - br label %bb -} - -declare double @llvm.pow.f64(double, double) nounwind readonly - -declare double @sin(double) nounwind readonly diff --git a/test/CodeGen/X86/pre-split5.ll b/test/CodeGen/X86/pre-split5.ll deleted file mode 100644 index 9f41f24..0000000 --- a/test/CodeGen/X86/pre-split5.ll +++ /dev/null @@ -1,56 +0,0 @@ -; RUN: llc < %s -march=x86 -mattr=+sse2 -pre-alloc-split -regalloc=linearscan - -target triple = "i386-apple-darwin9.5" - %struct.FILE = type { i8*, i32, i32, i16, i16, %struct.__sbuf, i32, i8*, i32 (i8*)*, i32 (i8*, i8*, i32)*, i64 (i8*, i64, i32)*, i32 (i8*, i8*, i32)*, %struct.__sbuf, %struct.__sFILEX*, i32, [3 x i8], [1 x i8], %struct.__sbuf, i32, i64 } - %struct.__sFILEX = type opaque - %struct.__sbuf = type { i8*, i32 } -@"\01LC1" = external constant [48 x i8] ; <[48 x i8]*> [#uses=1] - -define i32 @main() nounwind { -entry: - br label %bb5.us - -bb5.us: ; preds = %bb8.split, %bb5.us, %entry - %i.0.reg2mem.0.ph = phi i32 [ 0, %entry ], [ %indvar.next53, %bb8.split ], [ %i.0.reg2mem.0.ph, %bb5.us ] ; [#uses=2] - %j.0.reg2mem.0.us = phi i32 [ %indvar.next47, %bb5.us ], [ 0, %bb8.split ], [ 0, %entry ] ; [#uses=1] - %indvar.next47 = add i32 %j.0.reg2mem.0.us, 1 ; [#uses=2] - %exitcond48 = icmp eq i32 %indvar.next47, 256 ; [#uses=1] - br i1 %exitcond48, label %bb8.split, label %bb5.us - -bb8.split: ; preds = %bb5.us - %indvar.next53 = add i32 %i.0.reg2mem.0.ph, 1 ; [#uses=2] - %exitcond54 = icmp eq i32 %indvar.next53, 256 ; [#uses=1] - br i1 %exitcond54, label %bb11, label %bb5.us - -bb11: ; preds = %bb11, %bb8.split - %i.1.reg2mem.0 = phi i32 [ %indvar.next44, %bb11 ], [ 0, %bb8.split ] ; [#uses=1] - %indvar.next44 = add i32 %i.1.reg2mem.0, 1 ; [#uses=2] - %exitcond45 = icmp eq i32 %indvar.next44, 63 ; [#uses=1] - br i1 %exitcond45, label %bb14, label %bb11 - -bb14: ; preds = %bb14, %bb11 - %indvar = phi i32 [ %indvar.next40, %bb14 ], [ 0, %bb11 ] ; [#uses=1] - %indvar.next40 = add i32 %indvar, 1 ; [#uses=2] - %exitcond41 = icmp eq i32 %indvar.next40, 32768 ; [#uses=1] - br i1 %exitcond41, label %bb28, label %bb14 - -bb28: ; preds = %bb14 - %0 = fdiv double 2.550000e+02, 0.000000e+00 ; [#uses=1] - br label %bb30 - -bb30: ; preds = %bb36, %bb28 - %m.1.reg2mem.0 = phi i32 [ %m.0, %bb36 ], [ 0, %bb28 ] ; [#uses=1] - %1 = fmul double 0.000000e+00, %0 ; [#uses=1] - %2 = fptosi double %1 to i32 ; [#uses=1] - br i1 false, label %bb36, label %bb35 - -bb35: ; preds = %bb30 - %3 = tail call i32 (%struct.FILE*, i8*, ...)* @fprintf(%struct.FILE* null, i8* getelementptr ([48 x i8]* @"\01LC1", i32 0, i32 0), i32 0, i32 0, i32 0, i32 %2) nounwind ; [#uses=0] - br label %bb36 - -bb36: ; preds = %bb35, %bb30 - %m.0 = phi i32 [ 0, %bb35 ], [ %m.1.reg2mem.0, %bb30 ] ; [#uses=1] - br label %bb30 -} - -declare i32 @fprintf(%struct.FILE*, i8*, ...) nounwind diff --git a/test/CodeGen/X86/pre-split6.ll b/test/CodeGen/X86/pre-split6.ll deleted file mode 100644 index d8f274d..0000000 --- a/test/CodeGen/X86/pre-split6.ll +++ /dev/null @@ -1,36 +0,0 @@ -; RUN: llc < %s -mtriple=i386-apple-darwin -mattr=+sse2 -pre-alloc-split -regalloc=linearscan | grep {divsd 24} | count 1 - -@current_surfaces.b = external global i1 ; [#uses=1] - -declare double @sin(double) nounwind readonly - -declare double @asin(double) nounwind readonly - -define fastcc void @trace_line(i32 %line) nounwind { -entry: - %.b3 = load i1* @current_surfaces.b ; [#uses=1] - br i1 %.b3, label %bb.nph, label %return - -bb.nph: ; preds = %entry - %0 = load double* null, align 8 ; [#uses=1] - %1 = load double* null, align 8 ; [#uses=2] - %2 = fcmp une double %0, 0.000000e+00 ; [#uses=1] - br i1 %2, label %bb9.i, label %bb13.i - -bb9.i: ; preds = %bb.nph - %3 = tail call double @asin(double 0.000000e+00) nounwind readonly ; [#uses=0] - %4 = fdiv double 1.000000e+00, %1 ; [#uses=1] - %5 = fmul double %4, 0.000000e+00 ; [#uses=1] - %6 = tail call double @asin(double %5) nounwind readonly ; [#uses=0] - unreachable - -bb13.i: ; preds = %bb.nph - %7 = fdiv double 1.000000e+00, %1 ; [#uses=1] - %8 = tail call double @sin(double 0.000000e+00) nounwind readonly ; [#uses=1] - %9 = fmul double %7, %8 ; [#uses=1] - %10 = tail call double @asin(double %9) nounwind readonly ; [#uses=0] - unreachable - -return: ; preds = %entry - ret void -} diff --git a/test/CodeGen/X86/pre-split7.ll b/test/CodeGen/X86/pre-split7.ll deleted file mode 100644 index 8c93faa..0000000 --- a/test/CodeGen/X86/pre-split7.ll +++ /dev/null @@ -1,34 +0,0 @@ -; RUN: llc < %s -march=x86 -mattr=+sse2 -pre-alloc-split -regalloc=linearscan - -@object_distance = external global double, align 8 ; [#uses=1] -@axis_slope_angle = external global double, align 8 ; [#uses=1] -@current_surfaces.b = external global i1 ; [#uses=1] - -declare double @sin(double) nounwind readonly - -declare double @asin(double) nounwind readonly - -declare double @tan(double) nounwind readonly - -define fastcc void @trace_line(i32 %line) nounwind { -entry: - %.b3 = load i1* @current_surfaces.b ; [#uses=1] - br i1 %.b3, label %bb, label %return - -bb: ; preds = %bb, %entry - %0 = tail call double @asin(double 0.000000e+00) nounwind readonly ; [#uses=1] - %1 = fadd double 0.000000e+00, %0 ; [#uses=2] - %2 = tail call double @asin(double 0.000000e+00) nounwind readonly ; [#uses=1] - %3 = fsub double %1, %2 ; [#uses=2] - store double %3, double* @axis_slope_angle, align 8 - %4 = fdiv double %1, 2.000000e+00 ; [#uses=1] - %5 = tail call double @sin(double %4) nounwind readonly ; [#uses=1] - %6 = fmul double 0.000000e+00, %5 ; [#uses=1] - %7 = tail call double @tan(double %3) nounwind readonly ; [#uses=0] - %8 = fadd double 0.000000e+00, %6 ; [#uses=1] - store double %8, double* @object_distance, align 8 - br label %bb - -return: ; preds = %entry - ret void -} diff --git a/test/CodeGen/X86/pre-split8.ll b/test/CodeGen/X86/pre-split8.ll deleted file mode 100644 index 7e6ad6e..0000000 --- a/test/CodeGen/X86/pre-split8.ll +++ /dev/null @@ -1,35 +0,0 @@ -; RUN: llc < %s -march=x86 -mattr=+sse2 -pre-alloc-split -regalloc=linearscan -stats |& \ -; RUN: grep {pre-alloc-split} | grep {Number of intervals split} | grep 1 - -@current_surfaces.b = external global i1 ; [#uses=1] - -declare double @asin(double) nounwind readonly - -declare double @tan(double) nounwind readonly - -define fastcc void @trace_line(i32 %line) nounwind { -entry: - %.b3 = load i1* @current_surfaces.b ; [#uses=1] - br i1 %.b3, label %bb, label %return - -bb: ; preds = %bb9.i, %entry - %.rle4 = phi double [ %7, %bb9.i ], [ 0.000000e+00, %entry ] ; [#uses=1] - %0 = load double* null, align 8 ; [#uses=3] - %1 = fcmp une double %0, 0.000000e+00 ; [#uses=1] - br i1 %1, label %bb9.i, label %bb13.i - -bb9.i: ; preds = %bb - %2 = fsub double %.rle4, %0 ; [#uses=0] - %3 = tail call double @asin(double %.rle4) nounwind readonly ; [#uses=0] - %4 = fmul double 0.000000e+00, %0 ; [#uses=1] - %5 = tail call double @tan(double 0.000000e+00) nounwind readonly ; [#uses=0] - %6 = fmul double %4, 0.000000e+00 ; [#uses=1] - %7 = fadd double %6, 0.000000e+00 ; [#uses=1] - br i1 false, label %return, label %bb - -bb13.i: ; preds = %bb - unreachable - -return: ; preds = %bb9.i, %entry - ret void -} diff --git a/test/CodeGen/X86/pre-split9.ll b/test/CodeGen/X86/pre-split9.ll deleted file mode 100644 index 951e6fb..0000000 --- a/test/CodeGen/X86/pre-split9.ll +++ /dev/null @@ -1,38 +0,0 @@ -; RUN: llc < %s -march=x86 -mattr=+sse2 -pre-alloc-split -regalloc=linearscan -stats |& \ -; RUN: grep {pre-alloc-split} | grep {Number of intervals split} | grep 1 - -@current_surfaces.b = external global i1 ; [#uses=1] - -declare double @sin(double) nounwind readonly - -declare double @asin(double) nounwind readonly - -declare double @tan(double) nounwind readonly - -define fastcc void @trace_line(i32 %line) nounwind { -entry: - %.b3 = load i1* @current_surfaces.b ; [#uses=1] - br i1 %.b3, label %bb, label %return - -bb: ; preds = %bb9.i, %entry - %.rle4 = phi double [ %8, %bb9.i ], [ 0.000000e+00, %entry ] ; [#uses=1] - %0 = load double* null, align 8 ; [#uses=3] - %1 = fcmp une double %0, 0.000000e+00 ; [#uses=1] - br i1 %1, label %bb9.i, label %bb13.i - -bb9.i: ; preds = %bb - %2 = fsub double %.rle4, %0 ; [#uses=0] - %3 = tail call double @asin(double %.rle4) nounwind readonly ; [#uses=0] - %4 = tail call double @sin(double 0.000000e+00) nounwind readonly ; [#uses=1] - %5 = fmul double %4, %0 ; [#uses=1] - %6 = tail call double @tan(double 0.000000e+00) nounwind readonly ; [#uses=0] - %7 = fmul double %5, 0.000000e+00 ; [#uses=1] - %8 = fadd double %7, 0.000000e+00 ; [#uses=1] - br i1 false, label %return, label %bb - -bb13.i: ; preds = %bb - unreachable - -return: ; preds = %bb9.i, %entry - ret void -} -- cgit v1.1 From 4db3748fcf39ac0001b9d02eb6bf803e309a5c19 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Mon, 27 Jun 2011 23:47:21 +0000 Subject: Remove RCBarriers from TargetInstrDesc. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133964 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Target/TargetInstrDesc.h | 12 -------- utils/TableGen/InstrInfoEmitter.cpp | 56 +---------------------------------- utils/TableGen/InstrInfoEmitter.h | 1 - 3 files changed, 1 insertion(+), 68 deletions(-) diff --git a/include/llvm/Target/TargetInstrDesc.h b/include/llvm/Target/TargetInstrDesc.h index ecd2acc..6a540ab 100644 --- a/include/llvm/Target/TargetInstrDesc.h +++ b/include/llvm/Target/TargetInstrDesc.h @@ -130,7 +130,6 @@ public: uint64_t TSFlags; // Target Specific Flag values const unsigned *ImplicitUses; // Registers implicitly read by this instr const unsigned *ImplicitDefs; // Registers implicitly defined by this instr - const TargetRegisterClass **RCBarriers; // Reg classes completely "clobbered" const TargetOperandInfo *OpInfo; // 'NumOperands' entries about operands /// getOperandConstraint - Returns the value of the specific constraint if @@ -251,17 +250,6 @@ public: return false; } - /// getRegClassBarriers - Return a list of register classes that are - /// completely clobbered by this machine instruction. For example, on X86 - /// the call instructions will completely clobber all the registers in the - /// fp stack and XMM classes. - /// - /// This method returns null if the instruction doesn't completely clobber - /// any register class. - const TargetRegisterClass **getRegClassBarriers() const { - return RCBarriers; - } - /// getSchedClass - Return the scheduling class for this instruction. The /// scheduling class is an index into the InstrItineraryData table. This /// returns zero if there is no known scheduling information for the diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp index 6a96696..22c1004 100644 --- a/utils/TableGen/InstrInfoEmitter.cpp +++ b/utils/TableGen/InstrInfoEmitter.cpp @@ -27,14 +27,6 @@ static void PrintDefList(const std::vector &Uses, OS << "0 };\n"; } -static void PrintBarriers(std::vector &Barriers, - unsigned Num, raw_ostream &OS) { - OS << "static const TargetRegisterClass* Barriers" << Num << "[] = { "; - for (unsigned i = 0, e = Barriers.size(); i != e; ++i) - OS << "&" << getQualifiedName(Barriers[i]) << "RegClass, "; - OS << "NULL };\n"; -} - //===----------------------------------------------------------------------===// // Instruction Itinerary Information. //===----------------------------------------------------------------------===// @@ -158,33 +150,6 @@ void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS, } } -void InstrInfoEmitter::DetectRegisterClassBarriers(std::vector &Defs, - const std::vector &RCs, - std::vector &Barriers) { - std::set DefSet; - unsigned NumDefs = Defs.size(); - for (unsigned i = 0; i < NumDefs; ++i) - DefSet.insert(Defs[i]); - - for (unsigned i = 0, e = RCs.size(); i != e; ++i) { - const CodeGenRegisterClass &RC = RCs[i]; - ArrayRef Order = RC.getOrder(); - if (Order.size() > NumDefs) - continue; // Can't possibly clobber this RC. - - bool Clobber = true; - for (unsigned j = 0; j < Order.size(); ++j) { - Record *Reg = Order[j]; - if (!DefSet.count(Reg)) { - Clobber = false; - break; - } - } - if (Clobber) - Barriers.push_back(RC.TheDef); - } -} - //===----------------------------------------------------------------------===// // Main Output. //===----------------------------------------------------------------------===// @@ -199,14 +164,10 @@ void InstrInfoEmitter::run(raw_ostream &OS) { CodeGenTarget &Target = CDP.getTargetInfo(); const std::string &TargetName = Target.getName(); Record *InstrInfo = Target.getInstructionSet(); - const std::vector &RCs = Target.getRegisterClasses(); // Keep track of all of the def lists we have emitted already. std::map, unsigned> EmittedLists; unsigned ListNumber = 0; - std::map, unsigned> EmittedBarriers; - unsigned BarrierNumber = 0; - std::map BarriersMap; // Emit all of the instruction's implicit uses and defs. for (CodeGenTarget::inst_iterator II = Target.inst_begin(), @@ -219,14 +180,6 @@ void InstrInfoEmitter::run(raw_ostream &OS) { } std::vector Defs = Inst->getValueAsListOfDefs("Defs"); if (!Defs.empty()) { - std::vector RCBarriers; - DetectRegisterClassBarriers(Defs, RCs, RCBarriers); - if (!RCBarriers.empty()) { - unsigned &IB = EmittedBarriers[RCBarriers]; - if (!IB) PrintBarriers(RCBarriers, IB = ++BarrierNumber, OS); - BarriersMap.insert(std::make_pair(Inst, IB)); - } - unsigned &IL = EmittedLists[Defs]; if (!IL) PrintDefList(Defs, IL = ++ListNumber, OS); } @@ -246,7 +199,7 @@ void InstrInfoEmitter::run(raw_ostream &OS) { for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) emitRecord(*NumberedInstructions[i], i, InstrInfo, EmittedLists, - BarriersMap, OperandInfoIDs, OS); + OperandInfoIDs, OS); OS << "};\n"; OS << "} // End llvm namespace \n"; } @@ -254,7 +207,6 @@ void InstrInfoEmitter::run(raw_ostream &OS) { void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, Record *InstrInfo, std::map, unsigned> &EmittedLists, - std::map &BarriersMap, const OperandInfoMapTy &OpInfo, raw_ostream &OS) { int MinOperands = 0; @@ -322,12 +274,6 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, else OS << "ImplicitList" << EmittedLists[DefList] << ", "; - std::map::iterator BI = BarriersMap.find(Inst.TheDef); - if (BI == BarriersMap.end()) - OS << "NULL, "; - else - OS << "Barriers" << BI->second << ", "; - // Emit the operand info. std::vector OperandInfo = GetOperandInfo(Inst); if (OperandInfo.empty()) diff --git a/utils/TableGen/InstrInfoEmitter.h b/utils/TableGen/InstrInfoEmitter.h index abb1c6b..41672cc 100644 --- a/utils/TableGen/InstrInfoEmitter.h +++ b/utils/TableGen/InstrInfoEmitter.h @@ -44,7 +44,6 @@ private: void emitRecord(const CodeGenInstruction &Inst, unsigned Num, Record *InstrInfo, std::map, unsigned> &EL, - std::map &BM, const OperandInfoMapTy &OpInfo, raw_ostream &OS); -- cgit v1.1 From 6b8f1e35eacba34a11e2a7d5f614efc47b43d2e3 Mon Sep 17 00:00:00 2001 From: Jim Grosbach Date: Mon, 27 Jun 2011 23:54:06 +0000 Subject: ARM Assembly support for Thumb mov-immediate. Correctly parse the forms of the Thumb mov-immediate instruction: 1. 8-bit immediate 0-255. 2. 12-bit shifted-immediate. The 16-bit immediate "movw" form is also legal with just a "mov" mnemonic, but is not yet supported. More parser logic necessary there due to fixups. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133966 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMInstrThumb.td | 9 +++++---- lib/Target/ARM/ARMInstrThumb2.td | 9 +++++++++ lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 26 ++++++++++++++++++++++++++ test/MC/ARM/thumb2.s | 16 ++++++++++++++++ utils/TableGen/EDEmitter.cpp | 1 + 5 files changed, 57 insertions(+), 4 deletions(-) diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td index 44fbc02..328d330 100644 --- a/lib/Target/ARM/ARMInstrThumb.td +++ b/lib/Target/ARM/ARMInstrThumb.td @@ -34,9 +34,10 @@ def imm0_7_neg : PatLeaf<(i32 imm), [{ return (uint32_t)-N->getZExtValue() < 8; }], imm_neg_XFORM>; -def imm0_255 : ImmLeaf= 0 && Imm < 256; -}]>; +def imm0_255_asmoperand : AsmOperandClass { let Name = "Imm0_255"; } +def imm0_255 : Operand, ImmLeaf= 0 && Imm < 256; }]> { + let ParserMatchClass = imm0_255_asmoperand; +} def imm0_255_comp : PatLeaf<(i32 imm), [{ return ~((uint32_t)N->getZExtValue()) < 256; }]>; @@ -1072,7 +1073,7 @@ def tLSRrr : // A8.6.91 // Move register let isMoveImm = 1 in -def tMOVi8 : T1sI<(outs tGPR:$Rd), (ins i32imm:$imm8), IIC_iMOVi, +def tMOVi8 : T1sI<(outs tGPR:$Rd), (ins imm0_255:$imm8), IIC_iMOVi, "mov", "\t$Rd, $imm8", [(set tGPR:$Rd, imm0_255:$imm8)]>, T1General<{1,0,0,?,?}> { diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td index 090670b..f36a49e 100644 --- a/lib/Target/ARM/ARMInstrThumb2.td +++ b/lib/Target/ARM/ARMInstrThumb2.td @@ -44,9 +44,11 @@ def t2_so_imm_neg_XFORM : SDNodeXForm, ImmLeaf { + let ParserMatchClass = t2_so_imm_asmoperand; let EncoderMethod = "getT2SOImmOpValue"; } @@ -1645,6 +1647,10 @@ def t2MOVi : T2sOneRegImm<(outs rGPR:$Rd), (ins t2_so_imm:$imm), IIC_iMOVi, let Inst{15} = 0; } +def : InstAlias<"mov${s}${p} $Rd, $imm", (t2MOVi rGPR:$Rd, t2_so_imm:$imm, + pred:$p, cc_out:$s)>, + Requires<[IsThumb2]>; + let isReMaterializable = 1, isAsCheapAsAMove = 1, isMoveImm = 1 in def t2MOVi16 : T2I<(outs rGPR:$Rd), (ins i32imm_hilo16:$imm), IIC_iMOVi, "movw", "\t$Rd, $imm", @@ -2709,6 +2715,8 @@ def t2MOVCCr : T2TwoReg< let Inst{7-4} = 0b0000; } +// FIXME: Pseudo-ize these. For now, just mark codegen only. +let isCodeGenOnly = 1 in { let isMoveImm = 1 in def t2MOVCCi : T2OneRegImm<(outs rGPR:$Rd), (ins rGPR:$false, t2_so_imm:$imm), IIC_iCMOVi, "mov", ".w\t$Rd, $imm", @@ -2789,6 +2797,7 @@ def t2MOVCCror : T2I_movcc_sh<0b11, (outs rGPR:$Rd), IIC_iCMOVsi, "ror", ".w\t$Rd, $Rm, $imm", []>, RegConstraint<"$false = $Rd">; } // neverHasSideEffects +} // isCodeGenOnly = 1 //===----------------------------------------------------------------------===// // Atomic operations intrinsics diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 8fe504f..178fe52 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -350,6 +350,22 @@ public: bool isCondCode() const { return Kind == CondCode; } bool isCCOut() const { return Kind == CCOut; } bool isImm() const { return Kind == Immediate; } + bool isImm0_255() const { + if (Kind != Immediate) + return false; + const MCConstantExpr *CE = dyn_cast(getImm()); + if (!CE) return false; + int64_t Value = CE->getValue(); + return Value >= 0 && Value < 256; + } + bool isT2SOImm() const { + if (Kind != Immediate) + return false; + const MCConstantExpr *CE = dyn_cast(getImm()); + if (!CE) return false; + int64_t Value = CE->getValue(); + return ARM_AM::getT2SOImmVal(Value) != -1; + } bool isReg() const { return Kind == Register; } bool isRegList() const { return Kind == RegisterList; } bool isDPRRegList() const { return Kind == DPRRegisterList; } @@ -515,6 +531,16 @@ public: addExpr(Inst, getImm()); } + void addImm0_255Operands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + addExpr(Inst, getImm()); + } + + void addT2SOImmOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + addExpr(Inst, getImm()); + } + void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt()))); diff --git a/test/MC/ARM/thumb2.s b/test/MC/ARM/thumb2.s index 4e9d4e1..1a268a9 100644 --- a/test/MC/ARM/thumb2.s +++ b/test/MC/ARM/thumb2.s @@ -49,6 +49,22 @@ @ CHECK: mov.w r0, #66846720 @ encoding: [0x7f,0x70,0x4f,0xf0] mov.w r0, #66846720 +@ Aliases w/ the vanilla 'mov' mnemonic, and explicit alternative selection. + mov r2, #0xbf000000 + mov r1, #0x100 + mov r3, #32 + mov.w r3, #32 + movw r3, #32 + +@ CHECK: mov.w r2, #3204448256 @ encoding: [0x4f,0xf0,0x3f,0x42] +@ CHECK: mov.w r1, #256 @ encoding: [0x4f,0xf4,0x80,0x71] +@ CHECK: mov r3, #32 @ encoding: [0x20,0x23] +@ CHECK: mov.w r3, #32 @ encoding: [0x4f,0xf0,0x20,0x03] +@ CHECK: movw r3, #32 @ encoding: [0x40,0xf2,0x20,0x03] + + + + @ CHECK: rrx r0, r0 @ encoding: [0x30,0x00,0x4f,0xea] rrx r0, r0 diff --git a/utils/TableGen/EDEmitter.cpp b/utils/TableGen/EDEmitter.cpp index daf9617..4c0d385 100644 --- a/utils/TableGen/EDEmitter.cpp +++ b/utils/TableGen/EDEmitter.cpp @@ -588,6 +588,7 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type, IMM("imm0_31"); IMM("imm0_31_m1"); IMM("nModImm"); + IMM("imm0_255"); IMM("imm0_4095"); IMM("jt2block_operand"); IMM("t_imm_s4"); -- cgit v1.1 From f46e7e3d7ff56d91572350c45ade83f4deea0139 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Mon, 27 Jun 2011 23:54:40 +0000 Subject: Remove RegClass2VRegMap from MachineRegisterInfo. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133967 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CodeGen/MachineRegisterInfo.h | 12 ------------ lib/CodeGen/MachineRegisterInfo.cpp | 14 -------------- 2 files changed, 26 deletions(-) diff --git a/include/llvm/CodeGen/MachineRegisterInfo.h b/include/llvm/CodeGen/MachineRegisterInfo.h index 74df8da..8754108 100644 --- a/include/llvm/CodeGen/MachineRegisterInfo.h +++ b/include/llvm/CodeGen/MachineRegisterInfo.h @@ -32,11 +32,6 @@ class MachineRegisterInfo { IndexedMap, VirtReg2IndexFunctor> VRegInfo; - /// RegClassVRegMap - This vector acts as a map from TargetRegisterClass to - /// virtual registers. For each target register class, it keeps a list of - /// virtual registers belonging to the class. - std::vector *RegClass2VRegMap; - /// RegAllocHints - This vector records register allocation hints for virtual /// registers. For each virtual register, it keeps a register and hint type /// pair making up the allocation hint. Hint type is target specific except @@ -216,13 +211,6 @@ public: /// unsigned getNumVirtRegs() const { return VRegInfo.size(); } - /// getRegClassVirtRegs - Return the list of virtual registers of the given - /// target register class. - const std::vector & - getRegClassVirtRegs(const TargetRegisterClass *RC) const { - return RegClass2VRegMap[RC->getID()]; - } - /// setRegAllocationHint - Specify a register allocation hint for the /// specified virtual register. void setRegAllocationHint(unsigned Reg, unsigned Type, unsigned PrefReg) { diff --git a/lib/CodeGen/MachineRegisterInfo.cpp b/lib/CodeGen/MachineRegisterInfo.cpp index 08ff5bb..4b3e64c 100644 --- a/lib/CodeGen/MachineRegisterInfo.cpp +++ b/lib/CodeGen/MachineRegisterInfo.cpp @@ -20,7 +20,6 @@ using namespace llvm; MachineRegisterInfo::MachineRegisterInfo(const TargetRegisterInfo &TRI) { VRegInfo.reserve(256); RegAllocHints.reserve(256); - RegClass2VRegMap = new std::vector[TRI.getNumRegClasses()]; UsedPhysRegs.resize(TRI.getNumRegs()); // Create the physreg use/def lists. @@ -38,25 +37,13 @@ MachineRegisterInfo::~MachineRegisterInfo() { "PhysRegUseDefLists has entries after all instructions are deleted"); #endif delete [] PhysRegUseDefLists; - delete [] RegClass2VRegMap; } /// setRegClass - Set the register class of the specified virtual register. /// void MachineRegisterInfo::setRegClass(unsigned Reg, const TargetRegisterClass *RC) { - const TargetRegisterClass *OldRC = VRegInfo[Reg].first; VRegInfo[Reg].first = RC; - - // Remove from old register class's vregs list. This may be slow but - // fortunately this operation is rarely needed. - std::vector &VRegs = RegClass2VRegMap[OldRC->getID()]; - std::vector::iterator I = - std::find(VRegs.begin(), VRegs.end(), Reg); - VRegs.erase(I); - - // Add to new register class's vregs list. - RegClass2VRegMap[RC->getID()].push_back(Reg); } const TargetRegisterClass * @@ -95,7 +82,6 @@ MachineRegisterInfo::createVirtualRegister(const TargetRegisterClass *RegClass){ if (ArrayBase && &VRegInfo[FirstVirtReg] != ArrayBase) // The vector reallocated, handle this now. HandleVRegListReallocation(); - RegClass2VRegMap[RegClass->getID()].push_back(Reg); return Reg; } -- cgit v1.1 From adf7366771ebc78b3eee3c86b95e255ff5726da7 Mon Sep 17 00:00:00 2001 From: Jim Grosbach Date: Tue, 28 Jun 2011 00:19:13 +0000 Subject: ARM Thumb2 asm syntax optional destination operand for binary operators. When the destination operand is the same as the first source register operand for arithmetic instructions, the destination operand may be omitted. For example, the following two instructions are equivalent: and r1, #ff and r1, r1, #ff rdar://9672867 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133973 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMInstrThumb2.td | 38 +++++++++++++++++++++++++++++--------- test/MC/ARM/thumb2.s | 20 ++++++++++++++++++++ 2 files changed, 49 insertions(+), 9 deletions(-) diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td index f36a49e..06c63e3 100644 --- a/lib/Target/ARM/ARMInstrThumb2.td +++ b/lib/Target/ARM/ARMInstrThumb2.td @@ -465,7 +465,8 @@ multiclass T2I_un_irs opcod, string opc, /// changed to modify CPSR. multiclass T2I_bin_irs opcod, string opc, InstrItinClass iii, InstrItinClass iir, InstrItinClass iis, - PatFrag opnode, bit Commutable = 0, string wide = ""> { + PatFrag opnode, string baseOpc, bit Commutable = 0, + string wide = ""> { // shifted imm def ri : T2sTwoRegImm< (outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_imm:$imm), iii, @@ -497,14 +498,31 @@ multiclass T2I_bin_irs opcod, string opc, let Inst{26-25} = 0b01; let Inst{24-21} = opcod; } + // Assembly aliases for optional destination operand when it's the same + // as the source operand. + def : InstAlias(!strconcat(baseOpc, "ri")) rGPR:$Rdn, rGPR:$Rdn, + t2_so_imm:$imm, pred:$p, + cc_out:$s)>, + Requires<[IsThumb2]>; + def : InstAlias(!strconcat(baseOpc, "rr")) rGPR:$Rdn, rGPR:$Rdn, + rGPR:$Rm, pred:$p, + cc_out:$s)>, + Requires<[IsThumb2]>; + def : InstAlias(!strconcat(baseOpc, "rs")) rGPR:$Rdn, rGPR:$Rdn, + t2_so_reg:$shift, pred:$p, + cc_out:$s)>, + Requires<[IsThumb2]>; } /// T2I_bin_w_irs - Same as T2I_bin_irs except these operations need -// the ".w" prefix to indicate that they are wide. +// the ".w" suffix to indicate that they are wide. multiclass T2I_bin_w_irs opcod, string opc, InstrItinClass iii, InstrItinClass iir, InstrItinClass iis, - PatFrag opnode, bit Commutable = 0> : - T2I_bin_irs; + PatFrag opnode, string baseOpc, bit Commutable = 0> : + T2I_bin_irs; /// T2I_rbin_is - Same as T2I_bin_irs except the order of operands are /// reversed. The 'rr' form is only defined for the disassembler; for codegen @@ -2069,17 +2087,18 @@ def t2MOVsra_flag : T2TwoRegShiftImm< defm t2AND : T2I_bin_w_irs<0b0000, "and", IIC_iBITi, IIC_iBITr, IIC_iBITsi, - BinOpFrag<(and node:$LHS, node:$RHS)>, 1>; + BinOpFrag<(and node:$LHS, node:$RHS)>, "t2AND", 1>; defm t2ORR : T2I_bin_w_irs<0b0010, "orr", IIC_iBITi, IIC_iBITr, IIC_iBITsi, - BinOpFrag<(or node:$LHS, node:$RHS)>, 1>; + BinOpFrag<(or node:$LHS, node:$RHS)>, "t2ORR", 1>; defm t2EOR : T2I_bin_w_irs<0b0100, "eor", IIC_iBITi, IIC_iBITr, IIC_iBITsi, - BinOpFrag<(xor node:$LHS, node:$RHS)>, 1>; + BinOpFrag<(xor node:$LHS, node:$RHS)>, "t2EOR", 1>; defm t2BIC : T2I_bin_w_irs<0b0001, "bic", IIC_iBITi, IIC_iBITr, IIC_iBITsi, - BinOpFrag<(and node:$LHS, (not node:$RHS))>>; + BinOpFrag<(and node:$LHS, (not node:$RHS))>, + "t2BIC">; class T2BitFI pattern> @@ -2179,7 +2198,8 @@ let Constraints = "$src = $Rd" in { defm t2ORN : T2I_bin_irs<0b0011, "orn", IIC_iBITi, IIC_iBITr, IIC_iBITsi, - BinOpFrag<(or node:$LHS, (not node:$RHS))>, 0, "">; + BinOpFrag<(or node:$LHS, (not node:$RHS))>, + "t2ORN", 0, "">; // Prefer over of t2EORri ra, rb, -1 because mvn has 16-bit version let AddedComplexity = 1 in diff --git a/test/MC/ARM/thumb2.s b/test/MC/ARM/thumb2.s index 1a268a9..41dda84 100644 --- a/test/MC/ARM/thumb2.s +++ b/test/MC/ARM/thumb2.s @@ -318,3 +318,23 @@ ldrexd r0, r1, [r0] @ CHECK: ssat16 r0, #7, r0 @ encoding: [0x20,0xf3,0x06,0x00] ssat16 r0, #7, r0 + + and r1, #0xff + and r1, r1, #0xff + orr r1, 0x100 + orr r1, r1, 0x100 + eor r1, 0x100 + eor r1, r1, 0x100 + bic r1, 0x100 + bic r1, r1, 0x100 + +@ CHECK: and r1, r1, #255 @ encoding: [0x01,0xf0,0xff,0x01] +@ CHECK: and r1, r1, #255 @ encoding: [0x01,0xf0,0xff,0x01] +@ CHECK: orr r1, r1, #256 @ encoding: [0x41,0xf4,0x80,0x71] +@ CHECK: orr r1, r1, #256 @ encoding: [0x41,0xf4,0x80,0x71] +@ CHECK: eor r1, r1, #256 @ encoding: [0x81,0xf4,0x80,0x71] +@ CHECK: eor r1, r1, #256 @ encoding: [0x81,0xf4,0x80,0x71] +@ CHECK: bic r1, r1, #256 @ encoding: [0x21,0xf4,0x80,0x71] +@ CHECK: bic r1, r1, #256 @ encoding: [0x21,0xf4,0x80,0x71] + + -- cgit v1.1 From 1e0bd63477da6e9b1dc5111bafba2b1cf143bfba Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Tue, 28 Jun 2011 01:18:58 +0000 Subject: Fix a bad iterator dereference that Evan uncovered. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133978 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/SplitKit.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/CodeGen/SplitKit.cpp b/lib/CodeGen/SplitKit.cpp index 18f315a..55b1114 100644 --- a/lib/CodeGen/SplitKit.cpp +++ b/lib/CodeGen/SplitKit.cpp @@ -76,12 +76,14 @@ SlotIndex SplitAnalysis::computeLastSplitPoint(unsigned Num) { return LSP.first; // There may not be a call instruction (?) in which case we ignore LPad. LSP.second = LSP.first; - for (MachineBasicBlock::const_iterator I = FirstTerm, E = MBB->begin(); - I != E; --I) + for (MachineBasicBlock::const_iterator I = MBB->end(), E = MBB->begin(); + I != E;) { + --I; if (I->getDesc().isCall()) { LSP.second = LIS.getInstructionIndex(I); break; } + } } // If CurLI is live into a landing pad successor, move the last split point -- cgit v1.1 From 4987033fbd8e774e67903f50a8bd20d539c4dca5 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Tue, 28 Jun 2011 01:36:01 +0000 Subject: Alternative name enum should go into the enum portion. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133979 91177308-0d34-0410-b5e6-96231b3b80d8 --- utils/TableGen/RegisterInfoEmitter.cpp | 35 ++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp index f8ce3ac..5753c80 100644 --- a/utils/TableGen/RegisterInfoEmitter.cpp +++ b/utils/TableGen/RegisterInfoEmitter.cpp @@ -57,7 +57,8 @@ RegisterInfoEmitter::runEnums(raw_ostream &OS, Target.getRegisterClasses(); if (!RegisterClasses.empty()) { OS << "\n// Register classes\n"; - OS << "namespace " << RegisterClasses[0].Namespace << " {\n"; + if (!Namespace.empty()) + OS << "namespace " << Namespace << " {\n"; OS << "enum {\n"; for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) { if (i) OS << ",\n"; @@ -65,9 +66,27 @@ RegisterInfoEmitter::runEnums(raw_ostream &OS, OS << " = " << i; } OS << "\n };\n"; - OS << "}\n"; + if (!Namespace.empty()) + OS << "}\n"; + } + + const std::vector RegAltNameIndices = Target.getRegAltNameIndices(); + // If the only definition is the default NoRegAltName, we don't need to + // emit anything. + if (RegAltNameIndices.size() > 1) { + OS << "\n// Register alternate name indices\n"; + if (!Namespace.empty()) + OS << "namespace " << Namespace << " {\n"; + OS << "enum {\n"; + for (unsigned i = 0, e = RegAltNameIndices.size(); i != e; ++i) + OS << " " << RegAltNameIndices[i]->getName() << ",\t// " << i << "\n"; + OS << " NUM_TARGET_REG_ALT_NAMES = " << RegAltNameIndices.size() << "\n"; + OS << "};\n"; + if (!Namespace.empty()) + OS << "}\n"; } + OS << "} // End llvm namespace \n"; OS << "#endif // GET_REGINFO_ENUM\n\n"; } @@ -112,18 +131,6 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, OS << "0 };\n"; } - const std::vector RegAltNameIndices = Target.getRegAltNameIndices(); - // If the only definition is the default NoRegAltName, we don't need to - // emit anything. - if (RegAltNameIndices.size() > 1) { - OS << "\n// Register alternate name indices\n"; - OS << "enum {\n"; - for (unsigned i = 0, e = RegAltNameIndices.size(); i != e; ++i) - OS << " " << RegAltNameIndices[i]->getName() << ",\t// " << i << "\n"; - OS << " NUM_TARGET_REG_ALT_NAMES = " << RegAltNameIndices.size() << "\n"; - OS << "};\n"; - } - // Emit the empty sub-registers list OS << " const unsigned Empty_SubRegsSet[] = { 0 };\n"; // Loop over all of the registers which have sub-registers, emitting the -- cgit v1.1 From f3f955b5b9f2b4d5a21b18e1821dca52d0c178f4 Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Tue, 28 Jun 2011 02:03:10 +0000 Subject: FileCheck-ize a test that had the strangest TCL quote I've seen yet: an opening single quote with no closing single quote, and with {} quotes "inside" of it. This broke some of our tools that scrape test cases. Also, while here, make the test actually assert what the comment says it asserts. This was essentially authored by Nick Lewycky, and merely typed in by myself. Let me know if this is still missing the mark, but the previous test only succeeded due to the improper quoting preventing *anything* from matching the grep -- it had a '4(%...)' sequence in the output! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133980 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/CodeGen/X86/longlong-deadload.ll | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/test/CodeGen/X86/longlong-deadload.ll b/test/CodeGen/X86/longlong-deadload.ll index 9a4c8f2..db91961e0 100644 --- a/test/CodeGen/X86/longlong-deadload.ll +++ b/test/CodeGen/X86/longlong-deadload.ll @@ -1,8 +1,11 @@ -; RUN: llc < %s -march=x86 | not grep '4{(%...)} +; RUN: llc < %s -march=x86 | FileCheck %s ; This should not load or store the top part of *P. define void @test(i64* %P) nounwind { -entry: +; CHECK: test: +; CHECK: movl 4(%esp), %[[REGISTER:.*]] +; CHECK-NOT: 4(%[[REGISTER]]) +; CHECK: ret %tmp1 = load i64* %P, align 8 ; [#uses=1] %tmp2 = xor i64 %tmp1, 1 ; [#uses=1] store i64 %tmp2, i64* %P, align 8 -- cgit v1.1 From 0b3b58df1bad0c0d05a36c943ea5ee9e8c9a5411 Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Tue, 28 Jun 2011 02:03:12 +0000 Subject: Fix CMake build by removing this now dead file. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133981 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/CodeGen/CMakeLists.txt b/lib/CodeGen/CMakeLists.txt index dae429c..92319c8 100644 --- a/lib/CodeGen/CMakeLists.txt +++ b/lib/CodeGen/CMakeLists.txt @@ -59,7 +59,6 @@ add_llvm_library(LLVMCodeGen Passes.cpp PeepholeOptimizer.cpp PostRASchedulerList.cpp - PreAllocSplitting.cpp ProcessImplicitDefs.cpp PrologEpilogInserter.cpp PseudoSourceValue.cpp -- cgit v1.1 From 15832f61775040995bb8aa6056176425bc2c9088 Mon Sep 17 00:00:00 2001 From: Andrew Trick Date: Tue, 28 Jun 2011 02:49:20 +0000 Subject: indvars --disable-iv-rewrite: Defer evaluating s/zext until SCEV evaluates all other IV exprs. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133982 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Scalar/IndVarSimplify.cpp | 97 +++++++++++++++++++------------- 1 file changed, 57 insertions(+), 40 deletions(-) diff --git a/lib/Transforms/Scalar/IndVarSimplify.cpp b/lib/Transforms/Scalar/IndVarSimplify.cpp index 1a87b15..126dbfd 100644 --- a/lib/Transforms/Scalar/IndVarSimplify.cpp +++ b/lib/Transforms/Scalar/IndVarSimplify.cpp @@ -86,21 +86,13 @@ namespace { DominatorTree *DT; TargetData *TD; - PHINode *CurrIV; // Current IV being simplified. - - // Instructions processed by SimplifyIVUsers for CurrIV. - SmallPtrSet Simplified; - - // Use-def pairs if IVUsers waiting to be processed for CurrIV. - SmallVector, 8> SimpleIVUsers; - SmallVector DeadInsts; bool Changed; public: static char ID; // Pass identification, replacement for typeid IndVarSimplify() : LoopPass(ID), IU(0), LI(0), SE(0), DT(0), TD(0), - CurrIV(0), Changed(false) { + Changed(false) { initializeIndVarSimplifyPass(*PassRegistry::getPassRegistry()); } @@ -132,7 +124,6 @@ namespace { void EliminateIVRemainder(BinaryOperator *Rem, Value *IVOperand, bool IsSigned); - void pushIVUsers(Instruction *Def); bool isSimpleIVUser(Instruction *I, const Loop *L); void RewriteNonIntegerIVs(Loop *L); @@ -1030,7 +1021,10 @@ bool IndVarSimplify::EliminateIVUser(Instruction *UseInst, /// pushIVUsers - Add all uses of Def to the current IV's worklist. /// -void IndVarSimplify::pushIVUsers(Instruction *Def) { +static void pushIVUsers( + Instruction *Def, + SmallPtrSet &Simplified, + SmallVectorImpl< std::pair > &SimpleIVUsers) { for (Value::use_iterator UI = Def->use_begin(), E = Def->use_end(); UI != E; ++UI) { @@ -1079,50 +1073,70 @@ bool IndVarSimplify::isSimpleIVUser(Instruction *I, const Loop *L) { /// Once DisableIVRewrite is default, LSR will be the only client of IVUsers. /// void IndVarSimplify::SimplifyIVUsersNoRewrite(Loop *L, SCEVExpander &Rewriter) { - // Simplification is performed independently for each IV, as represented by a - // loop header phi. Each round of simplification first iterates through the - // SimplifyIVUsers worklist, then determines whether the current IV should be - // widened. Widening adds a new phi to LoopPhis, inducing another round of - // simplification on the wide IV. + std::map WideIVMap; + SmallVector LoopPhis; for (BasicBlock::iterator I = L->getHeader()->begin(); isa(I); ++I) { LoopPhis.push_back(cast(I)); } + // Each round of simplification iterates through the SimplifyIVUsers worklist + // for all current phis, then determines whether any IVs can be + // widened. Widening adds new phis to LoopPhis, inducing another round of + // simplification on the wide IVs. while (!LoopPhis.empty()) { - CurrIV = LoopPhis.pop_back_val(); - Simplified.clear(); - assert(SimpleIVUsers.empty() && "expect empty IV users list"); + // Evaluate as many IV expressions as possible before widening any IVs. This + // forces SCEV to propagate no-wrap flags before evaluating sign/zero + // extension. The first time SCEV attempts to normalize sign/zero extension, + // the result becomes final. So for the most predictable results, we delay + // evaluation of sign/zero extend evaluation until needed, and avoid running + // other SCEV based analysis prior to SimplifyIVUsersNoRewrite. + do { + PHINode *CurrIV = LoopPhis.pop_back_val(); - WideIVInfo WI; + // Information about sign/zero extensions of CurrIV. + WideIVInfo WI; - pushIVUsers(CurrIV); + // Instructions processed by SimplifyIVUsers for CurrIV. + SmallPtrSet Simplified; - while (!SimpleIVUsers.empty()) { - Instruction *UseInst, *Operand; - tie(UseInst, Operand) = SimpleIVUsers.pop_back_val(); + // Use-def pairs if IVUsers waiting to be processed for CurrIV. + SmallVector, 8> SimpleIVUsers; - if (EliminateIVUser(UseInst, Operand)) { - pushIVUsers(Operand); - continue; - } - if (CastInst *Cast = dyn_cast(UseInst)) { - bool IsSigned = Cast->getOpcode() == Instruction::SExt; - if (IsSigned || Cast->getOpcode() == Instruction::ZExt) { - CollectExtend(Cast, IsSigned, WI, SE, TD); + pushIVUsers(CurrIV, Simplified, SimpleIVUsers); + + while (!SimpleIVUsers.empty()) { + Instruction *UseInst, *Operand; + tie(UseInst, Operand) = SimpleIVUsers.pop_back_val(); + + if (EliminateIVUser(UseInst, Operand)) { + pushIVUsers(Operand, Simplified, SimpleIVUsers); + continue; + } + if (CastInst *Cast = dyn_cast(UseInst)) { + bool IsSigned = Cast->getOpcode() == Instruction::SExt; + if (IsSigned || Cast->getOpcode() == Instruction::ZExt) { + CollectExtend(Cast, IsSigned, WI, SE, TD); + } + continue; + } + if (isSimpleIVUser(UseInst, L)) { + pushIVUsers(UseInst, Simplified, SimpleIVUsers); } - continue; } - if (isSimpleIVUser(UseInst, L)) { - pushIVUsers(UseInst); + if (WI.WidestNativeType) { + WideIVMap[CurrIV] = WI; } - } - if (WI.WidestNativeType) { - WidenIV Widener(CurrIV, WI, LI, SE, DT, DeadInsts); + } while(!LoopPhis.empty()); + + for (std::map::const_iterator I = WideIVMap.begin(), + E = WideIVMap.end(); I != E; ++I) { + WidenIV Widener(I->first, I->second, LI, SE, DT, DeadInsts); if (PHINode *WidePhi = Widener.CreateWideIV(Rewriter)) { Changed = true; LoopPhis.push_back(WidePhi); } } + WideIVMap.clear(); } } @@ -1145,8 +1159,6 @@ bool IndVarSimplify::runOnLoop(Loop *L, LPPassManager &LPM) { DT = &getAnalysis(); TD = getAnalysisIfAvailable(); - CurrIV = NULL; - Simplified.clear(); DeadInsts.clear(); Changed = false; @@ -1160,6 +1172,11 @@ bool IndVarSimplify::runOnLoop(Loop *L, LPPassManager &LPM) { SCEVExpander Rewriter(*SE); // Eliminate redundant IV users. + // + // Simplification works best when run before other consumers of SCEV. We + // attempt to avoid evaluating SCEVs for sign/zero extend operations until + // other expressions involving loop IVs have been evaluated. This helps SCEV + // propagate no-wrap flags before normalizing sign/zero extension. if (DisableIVRewrite) { Rewriter.disableCanonicalMode(); SimplifyIVUsersNoRewrite(L, Rewriter); -- cgit v1.1 From 56caa098085977c14cfab39d92c7dfa15dde0d90 Mon Sep 17 00:00:00 2001 From: Andrew Trick Date: Tue, 28 Jun 2011 03:01:46 +0000 Subject: indvars --disable-iv-rewrite: sever ties with IVUsers. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133988 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/IVUsers.cpp | 15 --------------- lib/Transforms/Scalar/IndVarSimplify.cpp | 12 ++++++------ 2 files changed, 6 insertions(+), 21 deletions(-) diff --git a/lib/Analysis/IVUsers.cpp b/lib/Analysis/IVUsers.cpp index ba4419c..7a9dc0f 100644 --- a/lib/Analysis/IVUsers.cpp +++ b/lib/Analysis/IVUsers.cpp @@ -21,7 +21,6 @@ #include "llvm/Analysis/Dominators.h" #include "llvm/Analysis/LoopPass.h" #include "llvm/Analysis/ScalarEvolutionExpressions.h" -#include "llvm/Support/CommandLine.h" #include "llvm/Target/TargetData.h" #include "llvm/Assembly/Writer.h" #include "llvm/ADT/STLExtras.h" @@ -39,15 +38,6 @@ INITIALIZE_PASS_DEPENDENCY(ScalarEvolution) INITIALIZE_PASS_END(IVUsers, "iv-users", "Induction Variable Users", false, true) -// IVUsers behavior currently depends on this temporary indvars mode. The -// option must be defined upstream from its uses. -namespace llvm { - bool DisableIVRewrite = false; -} -cl::opt DisableIVRewriteOpt( - "disable-iv-rewrite", cl::Hidden, cl::location(llvm::DisableIVRewrite), - cl::desc("Disable canonical induction variable rewriting")); - Pass *llvm::createIVUsersPass() { return new IVUsers(); } @@ -100,11 +90,6 @@ bool IVUsers::AddUsersIfInteresting(Instruction *I) { if (Width > 64 || (TD && !TD->isLegalInteger(Width))) return false; - // We expect Sign/Zero extension to be eliminated from the IR before analyzing - // any downstream uses. - if (DisableIVRewrite && (isa(I) || isa(I))) - return false; - if (!Processed.insert(I)) return true; // Instruction already handled. diff --git a/lib/Transforms/Scalar/IndVarSimplify.cpp b/lib/Transforms/Scalar/IndVarSimplify.cpp index 126dbfd..5876380 100644 --- a/lib/Transforms/Scalar/IndVarSimplify.cpp +++ b/lib/Transforms/Scalar/IndVarSimplify.cpp @@ -52,6 +52,7 @@ #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/LoopPass.h" #include "llvm/Support/CFG.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/Utils/Local.h" @@ -72,11 +73,9 @@ STATISTIC(NumElimExt , "Number of IV sign/zero extends eliminated"); STATISTIC(NumElimRem , "Number of IV remainder operations eliminated"); STATISTIC(NumElimCmp , "Number of IV comparisons eliminated"); -// DisableIVRewrite mode currently affects IVUsers, so is defined in libAnalysis -// and referenced here. -namespace llvm { - extern bool DisableIVRewrite; -} +static cl::opt DisableIVRewrite( + "disable-iv-rewrite", cl::Hidden, + cl::desc("Disable canonical induction variable rewriting")); namespace { class IndVarSimplify : public LoopPass { @@ -104,7 +103,8 @@ namespace { AU.addRequired(); AU.addRequiredID(LoopSimplifyID); AU.addRequiredID(LCSSAID); - AU.addRequired(); + if (!DisableIVRewrite) + AU.addRequired(); AU.addPreserved(); AU.addPreservedID(LoopSimplifyID); AU.addPreservedID(LCSSAID); -- cgit v1.1 From cee94d718b94235677e7aa7c2cebc458bab53dd2 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Tue, 28 Jun 2011 03:17:03 +0000 Subject: Fix cmake build. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133989 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/MBlaze/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Target/MBlaze/CMakeLists.txt b/lib/Target/MBlaze/CMakeLists.txt index 86d030d..498edd4 100644 --- a/lib/Target/MBlaze/CMakeLists.txt +++ b/lib/Target/MBlaze/CMakeLists.txt @@ -1,6 +1,6 @@ set(LLVM_TARGET_DEFINITIONS MBlaze.td) -tablegen(MBlazeGenRegisterInfo.h.inc -gen-register-info-header) +tablegen(MBlazeGenRegisterInfo.inc -gen-register-info) tablegen(MBlazeGenInstrNames.inc -gen-instr-enums) tablegen(MBlazeGenInstrInfo.inc -gen-instr-desc) tablegen(MBlazeGenCodeEmitter.inc -gen-emitter) -- cgit v1.1 From 89991d44136414c4c74eee7c6dfbdbeab287b881 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Tue, 28 Jun 2011 03:57:31 +0000 Subject: Fix typo in comment. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133990 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Utils/Local.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Transforms/Utils/Local.cpp b/lib/Transforms/Utils/Local.cpp index 506e5e8..b1dd733 100644 --- a/lib/Transforms/Utils/Local.cpp +++ b/lib/Transforms/Utils/Local.cpp @@ -642,7 +642,7 @@ bool llvm::EliminateDuplicatePHINodes(BasicBlock *BB) { bool Changed = false; // This implementation doesn't currently consider undef operands - // specially. Theroetically, two phis which are identical except for + // specially. Theoretically, two phis which are identical except for // one having an undef where the other doesn't could be collapsed. // Map from PHI hash values to PHI nodes. If multiple PHIs have -- cgit v1.1 From a5d950f673c29710d0e9e2afefe74b7003362a06 Mon Sep 17 00:00:00 2001 From: Andrew Trick Date: Tue, 28 Jun 2011 05:04:16 +0000 Subject: whitespace git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133991 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Scalar/LoopIdiomRecognize.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/Transforms/Scalar/LoopIdiomRecognize.cpp b/lib/Transforms/Scalar/LoopIdiomRecognize.cpp index dbf6eec..2fc114c 100644 --- a/lib/Transforms/Scalar/LoopIdiomRecognize.cpp +++ b/lib/Transforms/Scalar/LoopIdiomRecognize.cpp @@ -167,7 +167,7 @@ static void deleteDeadInstruction(Instruction *I, ScalarEvolution &SE) { static void deleteIfDeadInstruction(Value *V, ScalarEvolution &SE) { if (Instruction *I = dyn_cast(V)) if (isInstructionTriviallyDead(I)) - deleteDeadInstruction(I, SE); + deleteDeadInstruction(I, SE); } bool LoopIdiomRecognize::runOnLoop(Loop *L, LPPassManager &LPM) { @@ -468,7 +468,7 @@ processLoopStridedStore(Value *DestPtr, unsigned StoreSize, BasicBlock *Preheader = CurLoop->getLoopPreheader(); IRBuilder<> Builder(Preheader->getTerminator()); SCEVExpander Expander(*SE); - + // Okay, we have a strided store "p[i]" of a splattable value. We can turn // this into a memset in the loop preheader now if we want. However, this // would be unsafe to do if there is anything else in the loop that may read @@ -488,7 +488,7 @@ processLoopStridedStore(Value *DestPtr, unsigned StoreSize, deleteIfDeadInstruction(BasePtr, *SE); return false; } - + // Okay, everything looks good, insert the memset. // The # stored bytes is (BECount+1)*Size. Expand the trip count out to @@ -557,7 +557,7 @@ processLoopStoreOfLoopLoad(StoreInst *SI, unsigned StoreSize, BasicBlock *Preheader = CurLoop->getLoopPreheader(); IRBuilder<> Builder(Preheader->getTerminator()); SCEVExpander Expander(*SE); - + // Okay, we have a strided store "p[i]" of a loaded value. We can turn // this into a memcpy in the loop preheader now if we want. However, this // would be unsafe to do if there is anything else in the loop that may read @@ -568,7 +568,7 @@ processLoopStoreOfLoopLoad(StoreInst *SI, unsigned StoreSize, Expander.expandCodeFor(StoreEv->getStart(), Builder.getInt8PtrTy(SI->getPointerAddressSpace()), Preheader->getTerminator()); - + if (mayLoopAccessLocation(StoreBasePtr, AliasAnalysis::ModRef, CurLoop, BECount, StoreSize, getAnalysis(), SI)) { @@ -593,9 +593,9 @@ processLoopStoreOfLoopLoad(StoreInst *SI, unsigned StoreSize, deleteIfDeadInstruction(StoreBasePtr, *SE); return false; } - + // Okay, everything is safe, we can transform this! - + // The # stored bytes is (BECount+1)*Size. Expand the trip count out to // pointer size if it isn't already. @@ -619,7 +619,7 @@ processLoopStoreOfLoopLoad(StoreInst *SI, unsigned StoreSize, DEBUG(dbgs() << " Formed memcpy: " << *NewCall << "\n" << " from load ptr=" << *LoadEv << " at: " << *LI << "\n" << " from store ptr=" << *StoreEv << " at: " << *SI << "\n"); - + // Okay, the memset has been formed. Zap the original store and anything that // feeds into it. -- cgit v1.1 From 5e7645be4c9dd2193add44d30b5fef8036d7a3ce Mon Sep 17 00:00:00 2001 From: Andrew Trick Date: Tue, 28 Jun 2011 05:07:32 +0000 Subject: SCEVExpander: give new insts a name that identifies the reponsible pass. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133992 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Analysis/ScalarEvolutionExpander.h | 8 ++++++-- lib/Analysis/ScalarEvolutionExpander.cpp | 7 ++++--- lib/Transforms/Scalar/IndVarSimplify.cpp | 2 +- lib/Transforms/Scalar/LoopIdiomRecognize.cpp | 4 ++-- lib/Transforms/Scalar/LoopStrengthReduce.cpp | 2 +- 5 files changed, 14 insertions(+), 9 deletions(-) diff --git a/include/llvm/Analysis/ScalarEvolutionExpander.h b/include/llvm/Analysis/ScalarEvolutionExpander.h index 39d378e..6879fa6 100644 --- a/include/llvm/Analysis/ScalarEvolutionExpander.h +++ b/include/llvm/Analysis/ScalarEvolutionExpander.h @@ -30,6 +30,10 @@ namespace llvm { /// memory. class SCEVExpander : public SCEVVisitor { ScalarEvolution &SE; + + // New instructions receive a name to identifies them with the current pass. + const char* Label; + std::map, AssertingVH > InsertedExpressions; std::set > InsertedValues; @@ -67,8 +71,8 @@ namespace llvm { public: /// SCEVExpander - Construct a SCEVExpander in "canonical" mode. - explicit SCEVExpander(ScalarEvolution &se) - : SE(se), IVIncInsertLoop(0), CanonicalMode(true), + explicit SCEVExpander(ScalarEvolution &se, const char *label) + : SE(se), Label(label), IVIncInsertLoop(0), CanonicalMode(true), Builder(se.getContext(), TargetFolder(se.TD)) {} /// clear - Erase the contents of the InsertedExpressions map so that users diff --git a/lib/Analysis/ScalarEvolutionExpander.cpp b/lib/Analysis/ScalarEvolutionExpander.cpp index 0549935..b91d39b 100644 --- a/lib/Analysis/ScalarEvolutionExpander.cpp +++ b/lib/Analysis/ScalarEvolutionExpander.cpp @@ -936,7 +936,8 @@ SCEVExpander::getAddRecExprPHILiterally(const SCEVAddRecExpr *Normalized, BasicBlock *Header = L->getHeader(); Builder.SetInsertPoint(Header, Header->begin()); pred_iterator HPB = pred_begin(Header), HPE = pred_end(Header); - PHINode *PN = Builder.CreatePHI(ExpandTy, std::distance(HPB, HPE), "lsr.iv"); + PHINode *PN = Builder.CreatePHI(ExpandTy, std::distance(HPB, HPE), + Twine(Label) + ".iv"); rememberInstruction(PN); // Create the step instructions and populate the PHI. @@ -972,8 +973,8 @@ SCEVExpander::getAddRecExprPHILiterally(const SCEVAddRecExpr *Normalized, } } else { IncV = isNegative ? - Builder.CreateSub(PN, StepV, "lsr.iv.next") : - Builder.CreateAdd(PN, StepV, "lsr.iv.next"); + Builder.CreateSub(PN, StepV, Twine(Label) + ".iv.next") : + Builder.CreateAdd(PN, StepV, Twine(Label) + ".iv.next"); rememberInstruction(IncV); } PN->addIncoming(IncV, Pred); diff --git a/lib/Transforms/Scalar/IndVarSimplify.cpp b/lib/Transforms/Scalar/IndVarSimplify.cpp index 5876380..a2f2490 100644 --- a/lib/Transforms/Scalar/IndVarSimplify.cpp +++ b/lib/Transforms/Scalar/IndVarSimplify.cpp @@ -1169,7 +1169,7 @@ bool IndVarSimplify::runOnLoop(Loop *L, LPPassManager &LPM) { const SCEV *BackedgeTakenCount = SE->getBackedgeTakenCount(L); // Create a rewriter object which we'll use to transform the code with. - SCEVExpander Rewriter(*SE); + SCEVExpander Rewriter(*SE, "indvars"); // Eliminate redundant IV users. // diff --git a/lib/Transforms/Scalar/LoopIdiomRecognize.cpp b/lib/Transforms/Scalar/LoopIdiomRecognize.cpp index 2fc114c..a7bc0e0 100644 --- a/lib/Transforms/Scalar/LoopIdiomRecognize.cpp +++ b/lib/Transforms/Scalar/LoopIdiomRecognize.cpp @@ -467,7 +467,7 @@ processLoopStridedStore(Value *DestPtr, unsigned StoreSize, // header. This allows us to insert code for it in the preheader. BasicBlock *Preheader = CurLoop->getLoopPreheader(); IRBuilder<> Builder(Preheader->getTerminator()); - SCEVExpander Expander(*SE); + SCEVExpander Expander(*SE, "loop-idiom"); // Okay, we have a strided store "p[i]" of a splattable value. We can turn // this into a memset in the loop preheader now if we want. However, this @@ -556,7 +556,7 @@ processLoopStoreOfLoopLoad(StoreInst *SI, unsigned StoreSize, // header. This allows us to insert code for it in the preheader. BasicBlock *Preheader = CurLoop->getLoopPreheader(); IRBuilder<> Builder(Preheader->getTerminator()); - SCEVExpander Expander(*SE); + SCEVExpander Expander(*SE, "loop-idiom"); // Okay, we have a strided store "p[i]" of a loaded value. We can turn // this into a memcpy in the loop preheader now if we want. However, this diff --git a/lib/Transforms/Scalar/LoopStrengthReduce.cpp b/lib/Transforms/Scalar/LoopStrengthReduce.cpp index afa0bf8..c6ca99a 100644 --- a/lib/Transforms/Scalar/LoopStrengthReduce.cpp +++ b/lib/Transforms/Scalar/LoopStrengthReduce.cpp @@ -3698,7 +3698,7 @@ LSRInstance::ImplementSolution(const SmallVectorImpl &Solution, // we can remove them after we are done working. SmallVector DeadInsts; - SCEVExpander Rewriter(SE); + SCEVExpander Rewriter(SE, "lsr"); Rewriter.disableCanonicalMode(); Rewriter.setIVIncInsertPos(L, IVIncInsertPos); -- cgit v1.1 From dc8e546048db2f7ff5656742b2b26975098a11a0 Mon Sep 17 00:00:00 2001 From: Andrew Trick Date: Tue, 28 Jun 2011 05:41:52 +0000 Subject: Cleanup. Fix a stupid variable name. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133995 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/ScalarEvolutionExpander.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/Analysis/ScalarEvolutionExpander.cpp b/lib/Analysis/ScalarEvolutionExpander.cpp index b91d39b..530a8bf 100644 --- a/lib/Analysis/ScalarEvolutionExpander.cpp +++ b/lib/Analysis/ScalarEvolutionExpander.cpp @@ -937,7 +937,7 @@ SCEVExpander::getAddRecExprPHILiterally(const SCEVAddRecExpr *Normalized, Builder.SetInsertPoint(Header, Header->begin()); pred_iterator HPB = pred_begin(Header), HPE = pred_end(Header); PHINode *PN = Builder.CreatePHI(ExpandTy, std::distance(HPB, HPE), - Twine(Label) + ".iv"); + Twine(IVName) + ".iv"); rememberInstruction(PN); // Create the step instructions and populate the PHI. @@ -973,8 +973,8 @@ SCEVExpander::getAddRecExprPHILiterally(const SCEVAddRecExpr *Normalized, } } else { IncV = isNegative ? - Builder.CreateSub(PN, StepV, Twine(Label) + ".iv.next") : - Builder.CreateAdd(PN, StepV, Twine(Label) + ".iv.next"); + Builder.CreateSub(PN, StepV, Twine(IVName) + ".iv.next") : + Builder.CreateAdd(PN, StepV, Twine(IVName) + ".iv.next"); rememberInstruction(IncV); } PN->addIncoming(IncV, Pred); -- cgit v1.1 From 6d64a04a4d1c2f4f6f8877cc0811a4d4386e518f Mon Sep 17 00:00:00 2001 From: Andrew Trick Date: Tue, 28 Jun 2011 05:44:06 +0000 Subject: Cleanup. Fix a stupid variable name. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133996 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Analysis/ScalarEvolutionExpander.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/llvm/Analysis/ScalarEvolutionExpander.h b/include/llvm/Analysis/ScalarEvolutionExpander.h index 6879fa6..647a7dc 100644 --- a/include/llvm/Analysis/ScalarEvolutionExpander.h +++ b/include/llvm/Analysis/ScalarEvolutionExpander.h @@ -32,7 +32,7 @@ namespace llvm { ScalarEvolution &SE; // New instructions receive a name to identifies them with the current pass. - const char* Label; + const char* IVName; std::map, AssertingVH > InsertedExpressions; @@ -71,8 +71,8 @@ namespace llvm { public: /// SCEVExpander - Construct a SCEVExpander in "canonical" mode. - explicit SCEVExpander(ScalarEvolution &se, const char *label) - : SE(se), Label(label), IVIncInsertLoop(0), CanonicalMode(true), + explicit SCEVExpander(ScalarEvolution &se, const char *name) + : SE(se), IVName(name), IVIncInsertLoop(0), CanonicalMode(true), Builder(se.getContext(), TargetFolder(se.TD)) {} /// clear - Erase the contents of the InsertedExpressions map so that users -- cgit v1.1 From c1ce95fc256b6b83479304b67db58265f36af6ef Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Tue, 28 Jun 2011 06:25:03 +0000 Subject: FileCheckize a couple of tests. Also and add a test for popping dead return values and avoid testing the spill precision. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133997 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/CodeGen/X86/fp-stack-ret.ll | 27 +++++++++++++++++++++------ test/CodeGen/X86/pr1505b.ll | 25 +++++++++++++++++++++++-- 2 files changed, 44 insertions(+), 8 deletions(-) diff --git a/test/CodeGen/X86/fp-stack-ret.ll b/test/CodeGen/X86/fp-stack-ret.ll index c83a0cb..1307f70 100644 --- a/test/CodeGen/X86/fp-stack-ret.ll +++ b/test/CodeGen/X86/fp-stack-ret.ll @@ -1,25 +1,40 @@ -; RUN: llc < %s -mtriple=i686-apple-darwin8 -mcpu=yonah -march=x86 > %t -; RUN: grep fldl %t | count 1 -; RUN: not grep xmm %t -; RUN: grep {sub.*esp} %t | count 1 +; RUN: llc < %s -mtriple=i686-apple-darwin8 -mcpu=yonah -march=x86 | FileCheck %s ; These testcases shouldn't require loading into an XMM register then storing ; to memory, then reloading into an FPStack reg. +; CHECK: test1 +; CHECK: fldl +; CHECK-NEXT: ret define double @test1(double *%P) { %A = load double* %P ret double %A } -; fastcc should return a value +; fastcc should return a value +; CHECK: test2 +; CHECK-NOT: xmm +; CHECK: ret define fastcc double @test2(<2 x double> %A) { %B = extractelement <2 x double> %A, i32 0 ret double %B } +; CHECK: test3 +; CHECK: sub{{.*}}%esp +; CHECLK-NOT: xmm define fastcc double @test3(<4 x float> %A) { %B = bitcast <4 x float> %A to <2 x double> %C = call fastcc double @test2(<2 x double> %B) ret double %C } - + +; Clear the stack when not using a return value. +; CHECK: test4 +; CHECK: call +; CHECK: fstp +; CHECK: ret +define void @test4(double *%P) { + %A = call double @test1(double *%P) + ret void +} diff --git a/test/CodeGen/X86/pr1505b.ll b/test/CodeGen/X86/pr1505b.ll index 6a08dae..945ec4c 100644 --- a/test/CodeGen/X86/pr1505b.ll +++ b/test/CodeGen/X86/pr1505b.ll @@ -1,5 +1,4 @@ -; RUN: llc < %s -mcpu=i486 | grep fstpl | count 5 -; RUN: llc < %s -mcpu=i486 | grep fstps | count 2 +; RUN: llc < %s -mcpu=i486 | FileCheck %s ; PR1505 target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64" @@ -30,19 +29,41 @@ declare void @_ZNSt8ios_base4InitC1Ev(%"struct.std::ctype_base"*) declare i32 @__cxa_atexit(void (i8*)*, i8*, i8*) +; CHECK: main define i32 @main() { entry: +; CHECK: flds %tmp6 = volatile load float* @a ; [#uses=1] +; CHECK: fstps (%esp) +; CHECK: tanf %tmp9 = tail call float @tanf( float %tmp6 ) ; [#uses=1] +; Spill returned value: +; CHECK: fstp + +; CHECK: fldl %tmp12 = volatile load double* @b ; [#uses=1] +; CHECK: fstpl (%esp) +; CHECK: tan %tmp13 = tail call double @tan( double %tmp12 ) ; [#uses=1] +; Spill returned value: +; CHECK: fstp %tmp1314 = fptrunc double %tmp13 to float ; [#uses=1] %tmp16 = tail call %"struct.std::basic_ostream >"* @_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc( %"struct.std::basic_ostream >"* @_ZSt4cout, i8* getelementptr ([12 x i8]* @.str, i32 0, i32 0) ) ; <%"struct.std::basic_ostream >"*> [#uses=1] %tmp1920 = fpext float %tmp9 to double ; [#uses=1] +; reload: +; CHECK: fld +; CHECK: fstpl +; CHECK: ZNSolsEd %tmp22 = tail call %"struct.std::basic_ostream >"* @_ZNSolsEd( %"struct.std::basic_ostream >"* %tmp16, double %tmp1920 ) ; <%"struct.std::basic_ostream >"*> [#uses=1] %tmp30 = tail call %"struct.std::basic_ostream >"* @_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_( %"struct.std::basic_ostream >"* %tmp22 ) ; <%"struct.std::basic_ostream >"*> [#uses=0] +; reload: +; CHECK: fld +; CHECK: fstps +; CHECK: ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc %tmp34 = tail call %"struct.std::basic_ostream >"* @_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc( %"struct.std::basic_ostream >"* @_ZSt4cout, i8* getelementptr ([13 x i8]* @.str1, i32 0, i32 0) ) ; <%"struct.std::basic_ostream >"*> [#uses=1] %tmp3940 = fpext float %tmp1314 to double ; [#uses=1] +; CHECK: fstpl +; CHECK: ZNSolsEd %tmp42 = tail call %"struct.std::basic_ostream >"* @_ZNSolsEd( %"struct.std::basic_ostream >"* %tmp34, double %tmp3940 ) ; <%"struct.std::basic_ostream >"*> [#uses=1] %tmp51 = tail call %"struct.std::basic_ostream >"* @_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_( %"struct.std::basic_ostream >"* %tmp42 ) ; <%"struct.std::basic_ostream >"*> [#uses=0] ret i32 0 -- cgit v1.1 From 4086bb5ba58ed83dba4991599c00bfba34693d3a Mon Sep 17 00:00:00 2001 From: Andrew Trick Date: Tue, 28 Jun 2011 06:34:10 +0000 Subject: FileCheckify and prepare for -disable-iv-rewrite. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133998 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/Transforms/IndVarSimplify/ada-loops.ll | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/test/Transforms/IndVarSimplify/ada-loops.ll b/test/Transforms/IndVarSimplify/ada-loops.ll index 4a07d99..9e635fd 100644 --- a/test/Transforms/IndVarSimplify/ada-loops.ll +++ b/test/Transforms/IndVarSimplify/ada-loops.ll @@ -1,14 +1,18 @@ -; RUN: opt < %s -indvars -S > %t -; RUN: grep phi %t | count 4 -; RUN: grep {= phi i32} %t | count 4 -; RUN: not grep {sext i} %t -; RUN: not grep {zext i} %t -; RUN: not grep {trunc i} %t -; RUN: not grep {add i8} %t +; RUN: opt < %s -indvars -S | FileCheck %s +; RUN: opt < %s -indvars -disable-iv-rewrite -S | FileCheck %s +; ; PR1301 ; Do a bunch of analysis and prove that the loops can use an i32 trip ; count without casting. +; +; Note that all four functions should actually be converted to +; memset. However, this test case validates indvars behavior. We +; don't check that phis are "folded together" because that is a job +; for loop strength reduction. But indvars must remove sext, zext, +; trunc, and add i8. +; +; CHECK-NOT: {{sext|zext|trunc|add i8}} ; ModuleID = 'ada.bc' target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-n:8:16:32" -- cgit v1.1 From 4f91054fe4a593f23b46abe359d2df9aebc50f10 Mon Sep 17 00:00:00 2001 From: Jay Foad Date: Tue, 28 Jun 2011 08:24:19 +0000 Subject: PR10210: New method ConstantArray::getAsCString(). Use it in LTO to avoid getting embedded trailing null bytes in std::strings. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133999 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Constants.h | 6 ++++++ lib/VMCore/Constants.cpp | 31 +++++++++++++++++++++++-------- tools/lto/LTOModule.cpp | 2 +- 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/include/llvm/Constants.h b/include/llvm/Constants.h index ff59951..1afbb8a 100644 --- a/include/llvm/Constants.h +++ b/include/llvm/Constants.h @@ -387,6 +387,12 @@ public: /// std::string getAsString() const; + /// getAsCString - If this array is isCString(), then this method converts the + /// array (without the trailing null byte) to an std::string and returns it. + /// Otherwise, it asserts out. + /// + std::string getAsCString() const; + /// isNullValue - Return true if this is the value that would be returned by /// getNullValue. This always returns false because zero arrays are always /// created as ConstantAggregateZero objects. diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp index 87f2fe6..4e6e64d 100644 --- a/lib/VMCore/Constants.cpp +++ b/lib/VMCore/Constants.cpp @@ -1011,17 +1011,32 @@ bool ConstantArray::isCString() const { } -/// getAsString - If the sub-element type of this array is i8 -/// then this method converts the array to an std::string and returns it. -/// Otherwise, it asserts out. +/// convertToString - Helper function for getAsString() and getAsCString(). +static std::string convertToString(const User *U, unsigned len) +{ + std::string Result; + Result.reserve(len); + for (unsigned i = 0; i != len; ++i) + Result.push_back((char)cast(U->getOperand(i))->getZExtValue()); + return Result; +} + +/// getAsString - If this array is isString(), then this method converts the +/// array to an std::string and returns it. Otherwise, it asserts out. /// std::string ConstantArray::getAsString() const { assert(isString() && "Not a string!"); - std::string Result; - Result.reserve(getNumOperands()); - for (unsigned i = 0, e = getNumOperands(); i != e; ++i) - Result.push_back((char)cast(getOperand(i))->getZExtValue()); - return Result; + return convertToString(this, getNumOperands()); +} + + +/// getAsCString - If this array is isCString(), then this method converts the +/// array (without the trailing null byte) to an std::string and returns it. +/// Otherwise, it asserts out. +/// +std::string ConstantArray::getAsCString() const { + assert(isCString() && "Not a string!"); + return convertToString(this, getNumOperands() - 1); } diff --git a/tools/lto/LTOModule.cpp b/tools/lto/LTOModule.cpp index 8f2b1f4..fe8e6cf 100644 --- a/tools/lto/LTOModule.cpp +++ b/tools/lto/LTOModule.cpp @@ -191,7 +191,7 @@ bool LTOModule::objcClassNameFromExpression(Constant *c, std::string &name) { Constant *cn = gvn->getInitializer(); if (ConstantArray *ca = dyn_cast(cn)) { if (ca->isCString()) { - name = ".objc_class_name_" + ca->getAsString(); + name = ".objc_class_name_" + ca->getAsCString(); return true; } } -- cgit v1.1 From bdb226ec83adf2e052f80f31ead21006b240c82f Mon Sep 17 00:00:00 2001 From: Roman Divacky Date: Tue, 28 Jun 2011 15:30:42 +0000 Subject: Implement ISD::VAARG lowering on PPC32. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134005 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/PowerPC/PPCISelLowering.cpp | 128 ++++++++++++++++++++++++- test/CodeGen/PowerPC/ppc32-vaarg.ll | 167 +++++++++++++++++++++++++++++++++ 2 files changed, 290 insertions(+), 5 deletions(-) create mode 100644 test/CodeGen/PowerPC/ppc32-vaarg.ll diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp index c9b490b..b44b6c3 100644 --- a/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/lib/Target/PowerPC/PPCISelLowering.cpp @@ -215,10 +215,11 @@ PPCTargetLowering::PPCTargetLowering(PPCTargetMachine &TM) setOperationAction(ISD::VASTART , MVT::Other, Custom); // VAARG is custom lowered with the 32-bit SVR4 ABI. - if ( TM.getSubtarget().isSVR4ABI() - && !TM.getSubtarget().isPPC64()) + if (TM.getSubtarget().isSVR4ABI() + && !TM.getSubtarget().isPPC64()) { setOperationAction(ISD::VAARG, MVT::Other, Custom); - else + setOperationAction(ISD::VAARG, MVT::i64, Custom); + } else setOperationAction(ISD::VAARG, MVT::Other, Expand); // Use the default implementation. @@ -1262,9 +1263,110 @@ SDValue PPCTargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const { SDValue PPCTargetLowering::LowerVAARG(SDValue Op, SelectionDAG &DAG, const PPCSubtarget &Subtarget) const { + SDNode *Node = Op.getNode(); + EVT VT = Node->getValueType(0); + EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); + SDValue InChain = Node->getOperand(0); + SDValue VAListPtr = Node->getOperand(1); + const Value *SV = cast(Node->getOperand(2))->getValue(); + DebugLoc dl = Node->getDebugLoc(); + + assert(!Subtarget.isPPC64() && "LowerVAARG is PPC32 only"); + + // gpr_index + SDValue GprIndex = DAG.getExtLoad(ISD::ZEXTLOAD, dl, MVT::i32, InChain, + VAListPtr, MachinePointerInfo(SV), MVT::i8, + false, false, 0); + InChain = GprIndex.getValue(1); + + if (VT == MVT::i64) { + // Check if GprIndex is even + SDValue GprAnd = DAG.getNode(ISD::AND, dl, MVT::i32, GprIndex, + DAG.getConstant(1, MVT::i32)); + SDValue CC64 = DAG.getSetCC(dl, MVT::i32, GprAnd, + DAG.getConstant(0, MVT::i32), ISD::SETNE); + SDValue GprIndexPlusOne = DAG.getNode(ISD::ADD, dl, MVT::i32, GprIndex, + DAG.getConstant(1, MVT::i32)); + // Align GprIndex to be even if it isn't + GprIndex = DAG.getNode(ISD::SELECT, dl, MVT::i32, CC64, GprIndexPlusOne, + GprIndex); + } + + // fpr index is 1 byte after gpr + SDValue FprPtr = DAG.getNode(ISD::ADD, dl, PtrVT, VAListPtr, + DAG.getConstant(1, MVT::i32)); + + // fpr + SDValue FprIndex = DAG.getExtLoad(ISD::ZEXTLOAD, dl, MVT::i32, InChain, + FprPtr, MachinePointerInfo(SV), MVT::i8, + false, false, 0); + InChain = FprIndex.getValue(1); + + SDValue RegSaveAreaPtr = DAG.getNode(ISD::ADD, dl, PtrVT, VAListPtr, + DAG.getConstant(8, MVT::i32)); + + SDValue OverflowAreaPtr = DAG.getNode(ISD::ADD, dl, PtrVT, VAListPtr, + DAG.getConstant(4, MVT::i32)); - llvm_unreachable("VAARG not yet implemented for the SVR4 ABI!"); - return SDValue(); // Not reached + // areas + SDValue OverflowArea = DAG.getLoad(MVT::i32, dl, InChain, OverflowAreaPtr, + MachinePointerInfo(), false, false, 0); + InChain = OverflowArea.getValue(1); + + SDValue RegSaveArea = DAG.getLoad(MVT::i32, dl, InChain, RegSaveAreaPtr, + MachinePointerInfo(), false, false, 0); + InChain = RegSaveArea.getValue(1); + + // select overflow_area if index > 8 + SDValue CC = DAG.getSetCC(dl, MVT::i32, VT.isInteger() ? GprIndex : FprIndex, + DAG.getConstant(8, MVT::i32), ISD::SETLT); + + SDValue Area = DAG.getNode(ISD::SELECT, dl, MVT::i32, CC, RegSaveArea, + OverflowArea); + + // adjustment constant gpr_index * 4/8 + SDValue RegConstant = DAG.getNode(ISD::MUL, dl, MVT::i32, + VT.isInteger() ? GprIndex : FprIndex, + DAG.getConstant(VT.isInteger() ? 4 : 8, + MVT::i32)); + + // OurReg = RegSaveArea + RegConstant + SDValue OurReg = DAG.getNode(ISD::ADD, dl, PtrVT, RegSaveArea, + RegConstant); + + // Floating types are 32 bytes into RegSaveArea + if (VT.isFloatingPoint()) + OurReg = DAG.getNode(ISD::ADD, dl, PtrVT, OurReg, + DAG.getConstant(32, MVT::i32)); + + // increase {f,g}pr_index by 1 (or 2 if VT is i64) + SDValue IndexPlus1 = DAG.getNode(ISD::ADD, dl, MVT::i32, + VT.isInteger() ? GprIndex : FprIndex, + DAG.getConstant(VT == MVT::i64 ? 2 : 1, + MVT::i32)); + + InChain = DAG.getTruncStore(InChain, dl, IndexPlus1, + VT.isInteger() ? VAListPtr : FprPtr, + MachinePointerInfo(SV), + MVT::i8, false, false, 0); + + // determine if we should load from reg_save_area or overflow_area + SDValue Result = DAG.getNode(ISD::SELECT, dl, PtrVT, CC, OurReg, OverflowArea); + + // increase overflow_area by 4/8 if gpr/fpr > 8 + SDValue OverflowAreaPlusN = DAG.getNode(ISD::ADD, dl, PtrVT, OverflowArea, + DAG.getConstant(VT.isInteger() ? 4 : 8, + MVT::i32)); + + OverflowArea = DAG.getNode(ISD::SELECT, dl, MVT::i32, CC, OverflowArea, + OverflowAreaPlusN); + + InChain = DAG.getTruncStore(InChain, dl, OverflowArea, + OverflowAreaPtr, + MachinePointerInfo(), + MVT::i32, false, false, 0); + + return DAG.getLoad(VT, dl, InChain, Result, MachinePointerInfo(), false, false, 0); } SDValue PPCTargetLowering::LowerTRAMPOLINE(SDValue Op, @@ -4429,11 +4531,27 @@ SDValue PPCTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { void PPCTargetLowering::ReplaceNodeResults(SDNode *N, SmallVectorImpl&Results, SelectionDAG &DAG) const { + const TargetMachine &TM = getTargetMachine(); DebugLoc dl = N->getDebugLoc(); switch (N->getOpcode()) { default: assert(false && "Do not know how to custom type legalize this operation!"); return; + case ISD::VAARG: { + if (!TM.getSubtarget().isSVR4ABI() + || TM.getSubtarget().isPPC64()) + return; + + EVT VT = N->getValueType(0); + + if (VT == MVT::i64) { + SDValue NewNode = LowerVAARG(SDValue(N, 1), DAG, PPCSubTarget); + + Results.push_back(NewNode); + Results.push_back(NewNode.getValue(1)); + } + return; + } case ISD::FP_ROUND_INREG: { assert(N->getValueType(0) == MVT::ppcf128); assert(N->getOperand(0).getValueType() == MVT::ppcf128); diff --git a/test/CodeGen/PowerPC/ppc32-vaarg.ll b/test/CodeGen/PowerPC/ppc32-vaarg.ll new file mode 100644 index 0000000..6042991 --- /dev/null +++ b/test/CodeGen/PowerPC/ppc32-vaarg.ll @@ -0,0 +1,167 @@ +; RUN: llc -O0 < %s | FileCheck %s +;ModuleID = 'test.c' +target datalayout = "E-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v128:128:128-n32" +target triple = "powerpc-unknown-freebsd9.0" + +%struct.__va_list_tag = type { i8, i8, i16, i8*, i8* } + +@var1 = common global i64 0, align 8 +@var2 = common global double 0.0, align 8 +@var3 = common global i32 0, align 4 + +define void @ppcvaargtest(%struct.__va_list_tag* %ap) nounwind { + entry: + %x = va_arg %struct.__va_list_tag* %ap, i64; Get from r5,r6 +; CHECK: lbz 4, 0(3) +; CHECK-NEXT: lwz 5, 4(3) +; CHECK-NEXT: rlwinm 6, 4, 0, 31, 31 +; CHECK-NEXT: cmplwi 0, 6, 0 +; CHECK-NEXT: addi 6, 4, 1 +; CHECK-NEXT: stw 3, -4(1) +; CHECK-NEXT: stw 6, -8(1) +; CHECK-NEXT: stw 4, -12(1) +; CHECK-NEXT: stw 5, -16(1) +; CHECK-NEXT: bne 0, .LBB0_2 +; CHECK-NEXT: # BB#1: # %entry +; CHECK-NEXT: lwz 3, -12(1) +; CHECK-NEXT: stw 3, -8(1) +; CHECK-NEXT: .LBB0_2: # %entry +; CHECK-NEXT: lwz 3, -8(1) +; CHECK-NEXT: lwz 4, -4(1) +; CHECK-NEXT: lwz 5, 8(4) +; CHECK-NEXT: slwi 6, 3, 2 +; CHECK-NEXT: addi 7, 3, 2 +; CHECK-NEXT: cmpwi 0, 3, 8 +; CHECK-NEXT: lwz 3, -16(1) +; CHECK-NEXT: addi 8, 3, 4 +; CHECK-NEXT: add 5, 5, 6 +; CHECK-NEXT: mfcr 0 # cr0 +; CHECK-NEXT: stw 0, -20(1) +; CHECK-NEXT: stw 5, -24(1) +; CHECK-NEXT: stw 3, -28(1) +; CHECK-NEXT: stw 7, -32(1) +; CHECK-NEXT: stw 8, -36(1) +; CHECK-NEXT: blt 0, .LBB0_4 +; CHECK-NEXT: # BB#3: # %entry +; CHECK-NEXT: lwz 3, -36(1) +; CHECK-NEXT: stw 3, -28(1) +; CHECK-NEXT: .LBB0_4: # %entry +; CHECK-NEXT: lwz 3, -28(1) +; CHECK-NEXT: lwz 4, -32(1) +; CHECK-NEXT: lwz 5, -4(1) +; CHECK-NEXT: stb 4, 0(5) +; CHECK-NEXT: lwz 4, -24(1) +; CHECK-NEXT: lwz 0, -20(1) +; CHECK-NEXT: mtcrf 128, 0 +; CHECK-NEXT: stw 3, -40(1) +; CHECK-NEXT: stw 4, -44(1) +; CHECK-NEXT: blt 0, .LBB0_6 +; CHECK-NEXT: # BB#5: # %entry +; CHECK-NEXT: lwz 3, -16(1) +; CHECK-NEXT: stw 3, -44(1) +; CHECK-NEXT: .LBB0_6: # %entry +; CHECK-NEXT: lwz 3, -44(1) +; CHECK-NEXT: lwz 4, -40(1) +; CHECK-NEXT: lwz 5, -4(1) +; CHECK-NEXT: stw 4, 4(5) + store i64 %x, i64* @var1, align 8 +; CHECK-NEXT: lis 4, var1@ha +; CHECK-NEXT: lwz 6, 4(3) +; CHECK-NEXT: lwz 3, 0(3) +; CHECK-NEXT: la 7, var1@l(4) +; CHECK-NEXT: stw 3, var1@l(4) +; CHECK-NEXT: stw 6, 4(7) + %y = va_arg %struct.__va_list_tag* %ap, double; From f1 +; CHECK-NEXT: lbz 3, 1(5) +; CHECK-NEXT: lwz 4, 4(5) +; CHECK-NEXT: lwz 6, 8(5) +; CHECK-NEXT: slwi 7, 3, 3 +; CHECK-NEXT: add 6, 6, 7 +; CHECK-NEXT: addi 7, 3, 1 +; CHECK-NEXT: cmpwi 0, 3, 8 +; CHECK-NEXT: addi 3, 4, 8 +; CHECK-NEXT: addi 6, 6, 32 +; CHECK-NEXT: mr 8, 4 +; CHECK-NEXT: mfcr 0 # cr0 +; CHECK-NEXT: stw 0, -48(1) +; CHECK-NEXT: stw 4, -52(1) +; CHECK-NEXT: stw 6, -56(1) +; CHECK-NEXT: stw 7, -60(1) +; CHECK-NEXT: stw 3, -64(1) +; CHECK-NEXT: stw 8, -68(1) +; CHECK-NEXT: blt 0, .LBB0_8 +; CHECK-NEXT: # BB#7: # %entry +; CHECK-NEXT: lwz 3, -64(1) +; CHECK-NEXT: stw 3, -68(1) +; CHECK-NEXT: .LBB0_8: # %entry +; CHECK-NEXT: lwz 3, -68(1) +; CHECK-NEXT: lwz 4, -60(1) +; CHECK-NEXT: lwz 5, -4(1) +; CHECK-NEXT: stb 4, 1(5) +; CHECK-NEXT: lwz 4, -56(1) +; CHECK-NEXT: lwz 0, -48(1) +; CHECK-NEXT: mtcrf 128, 0 +; CHECK-NEXT: stw 4, -72(1) +; CHECK-NEXT: stw 3, -76(1) +; CHECK-NEXT: blt 0, .LBB0_10 +; CHECK-NEXT: # BB#9: # %entry +; CHECK-NEXT: lwz 3, -52(1) +; CHECK-NEXT: stw 3, -72(1) +; CHECK-NEXT: .LBB0_10: # %entry +; CHECK-NEXT: lwz 3, -72(1) +; CHECK-NEXT: lwz 4, -76(1) +; CHECK-NEXT: lwz 5, -4(1) +; CHECK-NEXT: stw 4, 4(5) +; CHECK-NEXT: lfd 0, 0(3) + store double %y, double* @var2, align 8 +; CHECK-NEXT: lis 3, var2@ha +; CHECK-NEXT: stfd 0, var2@l(3) + %z = va_arg %struct.__va_list_tag* %ap, i32; From r7 +; CHECK-NEXT: lbz 3, 0(5) +; CHECK-NEXT: lwz 4, 4(5) +; CHECK-NEXT: lwz 6, 8(5) +; CHECK-NEXT: slwi 7, 3, 2 +; CHECK-NEXT: addi 8, 3, 1 +; CHECK-NEXT: cmpwi 0, 3, 8 +; CHECK-NEXT: addi 3, 4, 4 +; CHECK-NEXT: add 6, 6, 7 +; CHECK-NEXT: mr 7, 4 +; CHECK-NEXT: stw 6, -80(1) +; CHECK-NEXT: stw 8, -84(1) +; CHECK-NEXT: stw 3, -88(1) +; CHECK-NEXT: stw 4, -92(1) +; CHECK-NEXT: stw 7, -96(1) +; CHECK-NEXT: mfcr 0 # cr0 +; CHECK-NEXT: stw 0, -100(1) +; CHECK-NEXT: blt 0, .LBB0_12 +; CHECK-NEXT: # BB#11: # %entry +; CHECK-NEXT: lwz 3, -88(1) +; CHECK-NEXT: stw 3, -96(1) +; CHECK-NEXT: .LBB0_12: # %entry +; CHECK-NEXT: lwz 3, -96(1) +; CHECK-NEXT: lwz 4, -84(1) +; CHECK-NEXT: lwz 5, -4(1) +; CHECK-NEXT: stb 4, 0(5) +; CHECK-NEXT: lwz 4, -80(1) +; CHECK-NEXT: lwz 0, -100(1) +; CHECK-NEXT: mtcrf 128, 0 +; CHECK-NEXT: stw 4, -104(1) +; CHECK-NEXT: stw 3, -108(1) +; CHECK-NEXT: blt 0, .LBB0_14 +; CHECK-NEXT: # BB#13: # %entry +; CHECK-NEXT: lwz 3, -92(1) +; CHECK-NEXT: stw 3, -104(1) +; CHECK-NEXT: .LBB0_14: # %entry +; CHECK-NEXT: lwz 3, -104(1) +; CHECK-NEXT: lwz 4, -108(1) +; CHECK-NEXT: lwz 5, -4(1) +; CHECK-NEXT: stw 4, 4(5) +; CHECK-NEXT: lwz 3, 0(3) + store i32 %z, i32* @var3, align 4 +; CHECK-NEXT: lis 4, var3@ha +; CHECK-NEXT: stw 3, var3@l(4) + ret void +; CHECK-NEXT: stw 5, -112(1) +; CHECK-NEXT: blr +} + -- cgit v1.1 From 8d4386efb777c639915b25a9cdc3d5978290044e Mon Sep 17 00:00:00 2001 From: Andrew Trick Date: Tue, 28 Jun 2011 16:32:01 +0000 Subject: cmake: Our MSVC build does not support config-time build mode. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134008 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 1fc26a0..b08c7ae 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -81,7 +81,7 @@ if(PYTHONINTERP_FOUND) set(ENABLE_SHARED ${LLVM_SHARED_LIBS_ENABLED}) set(SHLIBPATH_VAR ${SHLIBPATH_VAR}) - if(LLVM_ENABLE_ASSERTIONS) + if(LLVM_ENABLE_ASSERTIONS AND NOT MSVC_IDE) set(ENABLE_ASSERTIONS "1") else() set(ENABLE_ASSERTIONS "0") -- cgit v1.1 From 99a92f67c7ee0d428e18f35c91311a2baba6c03e Mon Sep 17 00:00:00 2001 From: Andrew Trick Date: Tue, 28 Jun 2011 16:45:04 +0000 Subject: cleanup: misleading comment. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134010 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Scalar/IndVarSimplify.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Transforms/Scalar/IndVarSimplify.cpp b/lib/Transforms/Scalar/IndVarSimplify.cpp index a2f2490..8986dbb 100644 --- a/lib/Transforms/Scalar/IndVarSimplify.cpp +++ b/lib/Transforms/Scalar/IndVarSimplify.cpp @@ -1085,7 +1085,7 @@ void IndVarSimplify::SimplifyIVUsersNoRewrite(Loop *L, SCEVExpander &Rewriter) { // simplification on the wide IVs. while (!LoopPhis.empty()) { // Evaluate as many IV expressions as possible before widening any IVs. This - // forces SCEV to propagate no-wrap flags before evaluating sign/zero + // forces SCEV to set no-wrap flags before evaluating sign/zero // extension. The first time SCEV attempts to normalize sign/zero extension, // the result becomes final. So for the most predictable results, we delay // evaluation of sign/zero extend evaluation until needed, and avoid running @@ -1176,7 +1176,7 @@ bool IndVarSimplify::runOnLoop(Loop *L, LPPassManager &LPM) { // Simplification works best when run before other consumers of SCEV. We // attempt to avoid evaluating SCEVs for sign/zero extend operations until // other expressions involving loop IVs have been evaluated. This helps SCEV - // propagate no-wrap flags before normalizing sign/zero extension. + // set no-wrap flags before normalizing sign/zero extension. if (DisableIVRewrite) { Rewriter.disableCanonicalMode(); SimplifyIVUsersNoRewrite(L, Rewriter); -- cgit v1.1 From 27ce3b96e51887995f94d8c78a6c7e79bf7cdcdd Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Tue, 28 Jun 2011 17:24:32 +0000 Subject: Print registers by name instead of by number. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134013 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/RegAllocFast.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/CodeGen/RegAllocFast.cpp b/lib/CodeGen/RegAllocFast.cpp index 0f27dfc..15b0111 100644 --- a/lib/CodeGen/RegAllocFast.cpp +++ b/lib/CodeGen/RegAllocFast.cpp @@ -423,7 +423,7 @@ void RAFast::definePhysReg(MachineInstr *MI, unsigned PhysReg, // Returns spillImpossible when PhysReg or an alias can't be spilled. unsigned RAFast::calcSpillCost(unsigned PhysReg) const { if (UsedInInstr.test(PhysReg)) { - DEBUG(dbgs() << "PhysReg: " << PhysReg << " is already used in instr.\n"); + DEBUG(dbgs() << PrintReg(PhysReg, TRI) << " is already used in instr.\n"); return spillImpossible; } switch (unsigned VirtReg = PhysRegState[PhysReg]) { @@ -432,15 +432,15 @@ unsigned RAFast::calcSpillCost(unsigned PhysReg) const { case regFree: return 0; case regReserved: - DEBUG(dbgs() << "VirtReg: " << VirtReg << " corresponding to PhysReg: " - << PhysReg << " is reserved already.\n"); + DEBUG(dbgs() << PrintReg(VirtReg, TRI) << " corresponding " + << PrintReg(PhysReg, TRI) << " is reserved already.\n"); return spillImpossible; default: return LiveVirtRegs.lookup(VirtReg).Dirty ? spillDirty : spillClean; } // This is a disabled register, add up cost of aliases. - DEBUG(dbgs() << "\tRegister: " << PhysReg << " is disabled.\n"); + DEBUG(dbgs() << PrintReg(PhysReg, TRI) << " is disabled.\n"); unsigned Cost = 0; for (const unsigned *AS = TRI->getAliasSet(PhysReg); unsigned Alias = *AS; ++AS) { @@ -515,7 +515,7 @@ void RAFast::allocVirtReg(MachineInstr *MI, LiveRegEntry &LRE, unsigned Hint) { unsigned BestReg = 0, BestCost = spillImpossible; for (ArrayRef::iterator I = AO.begin(), E = AO.end(); I != E; ++I) { unsigned Cost = calcSpillCost(*I); - DEBUG(dbgs() << "\tRegister: " << *I << "\n"); + DEBUG(dbgs() << "\tRegister: " << PrintReg(*I, TRI) << "\n"); DEBUG(dbgs() << "\tCost: " << Cost << "\n"); DEBUG(dbgs() << "\tBestCost: " << BestCost << "\n"); // Cost is 0 when all aliases are already disabled. @@ -726,7 +726,8 @@ void RAFast::handleThroughOperands(MachineInstr *MI, if (!MO.isReg() || (MO.isDef() && !MO.isEarlyClobber())) continue; unsigned Reg = MO.getReg(); if (!Reg || !TargetRegisterInfo::isPhysicalRegister(Reg)) continue; - DEBUG(dbgs() << "\tSetting reg " << Reg << " as used in instr\n"); + DEBUG(dbgs() << "\tSetting " << PrintReg(Reg, TRI) + << " as used in instr\n"); UsedInInstr.set(Reg); } -- cgit v1.1 From 118c9a0c494c97fe23c43f3e2aca553aea3a4f16 Mon Sep 17 00:00:00 2001 From: Chad Rosier Date: Tue, 28 Jun 2011 17:26:57 +0000 Subject: Remove warning: 'c0' may be used uninitialized in this function. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134014 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMISelLowering.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index bffaa1c..9c01446 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -6486,7 +6486,8 @@ static SDValue PerformVDUPLANECombine(SDNode *N, // elements are the same constant, C, and Log2(C) ranges from 1 to 32. static bool isConstVecPow2(SDValue ConstVec, bool isSigned, uint64_t &C) { - integerPart c0, cN; + integerPart cN; + integerPart c0 = 0; for (unsigned I = 0, E = ConstVec.getValueType().getVectorNumElements(); I != E; I++) { ConstantFPSDNode *C = dyn_cast(ConstVec.getOperand(I)); -- cgit v1.1 From bd35f27ce9ecf7a6e6e1028dfc8652023cab265b Mon Sep 17 00:00:00 2001 From: Chad Rosier Date: Tue, 28 Jun 2011 18:26:12 +0000 Subject: Reinstate r133516 "Remove some unnecessary uses of c_str()." A trailing null character in std::string was causing failures for a few ObjC and Obj-C++ tests when -flto was enabled. Revision 133999 resolved this issue. Thanks Jay! rdar://9685235 PR10210 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134017 91177308-0d34-0410-b5e6-96231b3b80d8 --- tools/lto/LTOModule.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/lto/LTOModule.cpp b/tools/lto/LTOModule.cpp index fe8e6cf..4e754f6 100644 --- a/tools/lto/LTOModule.cpp +++ b/tools/lto/LTOModule.cpp @@ -208,7 +208,7 @@ void LTOModule::addObjCClass(GlobalVariable *clgv) { if (objcClassNameFromExpression(c->getOperand(1), superclassName)) { NameAndAttributes info; StringMap::value_type &entry = - _undefines.GetOrCreateValue(superclassName.c_str()); + _undefines.GetOrCreateValue(superclassName); if (!entry.getValue().name) { const char *symbolName = entry.getKey().data(); info.name = symbolName; @@ -220,7 +220,7 @@ void LTOModule::addObjCClass(GlobalVariable *clgv) { std::string className; if (objcClassNameFromExpression(c->getOperand(2), className)) { StringSet::value_type &entry = - _defines.GetOrCreateValue(className.c_str()); + _defines.GetOrCreateValue(className); entry.setValue(1); NameAndAttributes info; info.name = entry.getKey().data(); @@ -243,7 +243,7 @@ void LTOModule::addObjCCategory(GlobalVariable *clgv) { NameAndAttributes info; StringMap::value_type &entry = - _undefines.GetOrCreateValue(targetclassName.c_str()); + _undefines.GetOrCreateValue(targetclassName); if (entry.getValue().name) return; @@ -264,7 +264,7 @@ void LTOModule::addObjCClassRef(GlobalVariable *clgv) { NameAndAttributes info; StringMap::value_type &entry = - _undefines.GetOrCreateValue(targetclassName.c_str()); + _undefines.GetOrCreateValue(targetclassName); if (entry.getValue().name) return; @@ -375,7 +375,7 @@ void LTOModule::addDefinedSymbol(GlobalValue *def, Mangler &mangler, // add to table of symbols NameAndAttributes info; - StringSet::value_type &entry = _defines.GetOrCreateValue(Buffer.c_str()); + StringSet::value_type &entry = _defines.GetOrCreateValue(Buffer); entry.setValue(1); StringRef Name = entry.getKey(); @@ -436,7 +436,7 @@ void LTOModule::addPotentialUndefinedSymbol(GlobalValue *decl, mangler.getNameWithPrefix(name, decl, false); StringMap::value_type &entry = - _undefines.GetOrCreateValue(name.c_str()); + _undefines.GetOrCreateValue(name); // we already have the symbol if (entry.getValue().name) -- cgit v1.1 From 9bbe4d6c004f25bc491e2583cce7bc91891f68c7 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Tue, 28 Jun 2011 18:32:28 +0000 Subject: Clean up the handling of the x87 fp stack to make it more robust. Drop the FpMov instructions, use plain COPY instead. Drop the FpSET/GET instruction for accessing fixed stack positions. Instead use normal COPY to/from ST registers around inline assembly, and provide a single new FpPOP_RETVAL instruction that can access the return value(s) from a call. This is still necessary since you cannot tell from the CALL instruction alone if it returns anything on the FP stack. Teach fast isel to use this. This provides a much more robust way of handling fixed stack registers - we can tolerate arbitrary FP stack instructions inserted around calls and inline assembly. Live range splitting could sometimes break x87 code by inserting spill code in unfortunate places. As a bonus we handle floating point inline assembly correctly now. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134018 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86FastISel.cpp | 16 +- lib/Target/X86/X86FloatingPoint.cpp | 485 ++++++++++++++++++++++----------- lib/Target/X86/X86ISelLowering.cpp | 11 +- lib/Target/X86/X86InstrFPStack.td | 40 +-- lib/Target/X86/X86RegisterInfo.cpp | 12 - lib/Target/X86/X86RegisterInfo.td | 25 +- test/CodeGen/X86/inline-asm-fpstack.ll | 169 ++++++++++++ 7 files changed, 531 insertions(+), 227 deletions(-) diff --git a/lib/Target/X86/X86FastISel.cpp b/lib/Target/X86/X86FastISel.cpp index 82f5d3a..a4d1c67 100644 --- a/lib/Target/X86/X86FastISel.cpp +++ b/lib/Target/X86/X86FastISel.cpp @@ -1848,16 +1848,18 @@ bool X86FastISel::DoSelectCall(const Instruction *I, const char *MemIntName) { // stack, but where we prefer to use the value in xmm registers, copy it // out as F80 and use a truncate to move it from fp stack reg to xmm reg. if ((RVLocs[i].getLocReg() == X86::ST0 || - RVLocs[i].getLocReg() == X86::ST1) && - isScalarFPTypeInSSEReg(RVLocs[0].getValVT())) { - CopyVT = MVT::f80; + RVLocs[i].getLocReg() == X86::ST1)) { + if (isScalarFPTypeInSSEReg(RVLocs[i].getValVT())) + CopyVT = MVT::f80; CopyReg = createResultReg(X86::RFP80RegisterClass); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(X86::FpPOP_RETVAL), + CopyReg); + } else { + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(TargetOpcode::COPY), + CopyReg).addReg(RVLocs[i].getLocReg()); + UsedRegs.push_back(RVLocs[i].getLocReg()); } - BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(TargetOpcode::COPY), - CopyReg).addReg(RVLocs[i].getLocReg()); - UsedRegs.push_back(RVLocs[i].getLocReg()); - if (CopyVT != RVLocs[i].getValVT()) { // Round the F80 the right size, which also moves to the appropriate xmm // register. This is accomplished by storing the F80 value in memory and diff --git a/lib/Target/X86/X86FloatingPoint.cpp b/lib/Target/X86/X86FloatingPoint.cpp index e16f217..3fb5493 100644 --- a/lib/Target/X86/X86FloatingPoint.cpp +++ b/lib/Target/X86/X86FloatingPoint.cpp @@ -37,6 +37,7 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/Passes.h" +#include "llvm/InlineAsm.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" @@ -134,11 +135,36 @@ namespace { unsigned Stack[8]; // FP Registers in each stack slot... unsigned StackTop; // The current top of the FP stack. + enum { + NumFPRegs = 16 // Including scratch pseudo-registers. + }; + // For each live FP register, point to its Stack[] entry. // The first entries correspond to FP0-FP6, the rest are scratch registers // used when we need slightly different live registers than what the // register allocator thinks. - unsigned RegMap[16]; + unsigned RegMap[NumFPRegs]; + + // Pending fixed registers - Inline assembly needs FP registers to appear + // in fixed stack slot positions. This is handled by copying FP registers + // to ST registers before the instruction, and copying back after the + // instruction. + // + // This is modeled with pending ST registers. NumPendingSTs is the number + // of ST registers (ST0-STn) we are tracking. PendingST[n] points to an FP + // register that holds the ST value. The ST registers are not moved into + // place until immediately before the instruction that needs them. + // + // It can happen that we need an ST register to be live when no FP register + // holds the value: + // + // %ST0 = COPY %FP4 + // + // When that happens, we allocate a scratch FP register to hold the ST + // value. That means every register in PendingST must be live. + + unsigned NumPendingSTs; + unsigned char PendingST[8]; // Set up our stack model to match the incoming registers to MBB. void setupBlockStack(); @@ -152,13 +178,15 @@ namespace { dbgs() << " FP" << Stack[i]; assert(RegMap[Stack[i]] == i && "Stack[] doesn't match RegMap[]!"); } + for (unsigned i = 0; i != NumPendingSTs; ++i) + dbgs() << ", ST" << i << " in FP" << unsigned(PendingST[i]); dbgs() << "\n"; } /// getSlot - Return the stack slot number a particular register number is /// in. unsigned getSlot(unsigned RegNo) const { - assert(RegNo < array_lengthof(RegMap) && "Regno out of range!"); + assert(RegNo < NumFPRegs && "Regno out of range!"); return RegMap[RegNo]; } @@ -170,12 +198,17 @@ namespace { /// getScratchReg - Return an FP register that is not currently in use. unsigned getScratchReg() { - for (int i = array_lengthof(RegMap) - 1; i >= 8; --i) + for (int i = NumFPRegs - 1; i >= 8; --i) if (!isLive(i)) return i; llvm_unreachable("Ran out of scratch FP registers"); } + /// isScratchReg - Returns trus if RegNo is a scratch FP register. + bool isScratchReg(unsigned RegNo) { + return RegNo > 8 && RegNo < NumFPRegs; + } + /// getStackEntry - Return the X86::FP register in register ST(i). unsigned getStackEntry(unsigned STi) const { if (STi >= StackTop) @@ -191,7 +224,7 @@ namespace { // pushReg - Push the specified FP register onto the stack. void pushReg(unsigned Reg) { - assert(Reg < array_lengthof(RegMap) && "Register number out of range!"); + assert(Reg < NumFPRegs && "Register number out of range!"); if (StackTop >= 8) report_fatal_error("Stack overflow!"); Stack[StackTop] = Reg; @@ -261,7 +294,14 @@ namespace { void handleCondMovFP(MachineBasicBlock::iterator &I); void handleSpecialFP(MachineBasicBlock::iterator &I); - bool translateCopy(MachineInstr*); + // Check if a COPY instruction is using FP registers. + bool isFPCopy(MachineInstr *MI) { + unsigned DstReg = MI->getOperand(0).getReg(); + unsigned SrcReg = MI->getOperand(1).getReg(); + + return X86::RFP80RegClass.contains(DstReg) || + X86::RFP80RegClass.contains(SrcReg); + } }; char FPS::ID = 0; } @@ -351,6 +391,7 @@ void FPS::bundleCFG(MachineFunction &MF) { bool FPS::processBasicBlock(MachineFunction &MF, MachineBasicBlock &BB) { bool Changed = false; MBB = &BB; + NumPendingSTs = 0; setupBlockStack(); @@ -362,7 +403,7 @@ bool FPS::processBasicBlock(MachineFunction &MF, MachineBasicBlock &BB) { if (MI->isInlineAsm()) FPInstClass = X86II::SpecialFP; - if (MI->isCopy() && translateCopy(MI)) + if (MI->isCopy() && isFPCopy(MI)) FPInstClass = X86II::SpecialFP; if (FPInstClass == X86II::NotFP) @@ -891,7 +932,8 @@ void FPS::shuffleStackTop(const unsigned char *FixStack, continue; // (Reg st0) (OldReg st0) = (Reg OldReg st0) moveToTop(Reg, I); - moveToTop(OldReg, I); + if (FixCount > 0) + moveToTop(OldReg, I); } DEBUG(dumpStack()); } @@ -1249,142 +1291,309 @@ void FPS::handleSpecialFP(MachineBasicBlock::iterator &I) { MachineInstr *MI = I; switch (MI->getOpcode()) { default: llvm_unreachable("Unknown SpecialFP instruction!"); - case X86::FpGET_ST0_32:// Appears immediately after a call returning FP type! - case X86::FpGET_ST0_64:// Appears immediately after a call returning FP type! - case X86::FpGET_ST0_80:// Appears immediately after a call returning FP type! - assert(StackTop == 0 && "Stack should be empty after a call!"); - pushReg(getFPReg(MI->getOperand(0))); - break; - case X86::FpGET_ST1_32:// Appears immediately after a call returning FP type! - case X86::FpGET_ST1_64:// Appears immediately after a call returning FP type! - case X86::FpGET_ST1_80:{// Appears immediately after a call returning FP type! - // FpGET_ST1 should occur right after a FpGET_ST0 for a call or inline asm. - // The pattern we expect is: - // CALL - // FP1 = FpGET_ST0 - // FP4 = FpGET_ST1 - // - // At this point, we've pushed FP1 on the top of stack, so it should be - // present if it isn't dead. If it was dead, we already emitted a pop to - // remove it from the stack and StackTop = 0. - - // Push FP4 as top of stack next. - pushReg(getFPReg(MI->getOperand(0))); + case TargetOpcode::COPY: { + // We handle three kinds of copies: FP <- FP, FP <- ST, and ST <- FP. + const MachineOperand &MO1 = MI->getOperand(1); + const MachineOperand &MO0 = MI->getOperand(0); + unsigned DstST = MO0.getReg() - X86::ST0; + unsigned SrcST = MO1.getReg() - X86::ST0; + bool KillsSrc = MI->killsRegister(MO1.getReg()); + + // ST = COPY FP. Set up a pending ST register. + if (DstST < 8) { + unsigned SrcFP = getFPReg(MO1); + assert(isLive(SrcFP) && "Cannot copy dead register"); + assert(!MO0.isDead() && "Cannot copy to dead ST register"); + + // Unallocated STs are marked as the nonexistent FP255. + while (NumPendingSTs <= DstST) + PendingST[NumPendingSTs++] = NumFPRegs; + + // STi could still be live from a previous inline asm. + if (isScratchReg(PendingST[DstST])) { + DEBUG(dbgs() << "Clobbering old ST in FP" << unsigned(PendingST[DstST]) + << '\n'); + freeStackSlotBefore(MI, PendingST[DstST]); + } - // If StackTop was 0 before we pushed our operand, then ST(0) must have been - // dead. In this case, the ST(1) value is the only thing that is live, so - // it should be on the TOS (after the pop that was emitted) and is. Just - // continue in this case. - if (StackTop == 1) + // When the source is killed, allocate a scratch FP register. + if (KillsSrc) { + unsigned Slot = getSlot(SrcFP); + unsigned SR = getScratchReg(); + PendingST[DstST] = SR; + Stack[Slot] = SR; + RegMap[SR] = Slot; + } else + PendingST[DstST] = SrcFP; break; - - // Because pushReg just pushed ST(1) as TOS, we now have to swap the two top - // elements so that our accounting is correct. - unsigned RegOnTop = getStackEntry(0); - unsigned RegNo = getStackEntry(1); - - // Swap the slots the regs are in. - std::swap(RegMap[RegNo], RegMap[RegOnTop]); - - // Swap stack slot contents. - if (RegMap[RegOnTop] >= StackTop) - report_fatal_error("Access past stack top!"); - std::swap(Stack[RegMap[RegOnTop]], Stack[StackTop-1]); - break; - } - case X86::FpSET_ST0_32: - case X86::FpSET_ST0_64: - case X86::FpSET_ST0_80: { - // FpSET_ST0_80 is generated by copyRegToReg for setting up inline asm - // arguments that use an st constraint. We expect a sequence of - // instructions: Fp_SET_ST0 Fp_SET_ST1? INLINEASM - unsigned Op0 = getFPReg(MI->getOperand(0)); - - if (!MI->killsRegister(X86::FP0 + Op0)) { - // Duplicate Op0 into a temporary on the stack top. - duplicateToTop(Op0, getScratchReg(), I); - } else { - // Op0 is killed, so just swap it into position. - moveToTop(Op0, I); } - --StackTop; // "Forget" we have something on the top of stack! - break; - } - case X86::FpSET_ST1_32: - case X86::FpSET_ST1_64: - case X86::FpSET_ST1_80: { - // Set up st(1) for inline asm. We are assuming that st(0) has already been - // set up by FpSET_ST0, and our StackTop is off by one because of it. - unsigned Op0 = getFPReg(MI->getOperand(0)); - // Restore the actual StackTop from before Fp_SET_ST0. - // Note we can't handle Fp_SET_ST1 without a preceding Fp_SET_ST0, and we - // are not enforcing the constraint. - ++StackTop; - unsigned RegOnTop = getStackEntry(0); // This reg must remain in st(0). - if (!MI->killsRegister(X86::FP0 + Op0)) { - duplicateToTop(Op0, getScratchReg(), I); - moveToTop(RegOnTop, I); - } else if (getSTReg(Op0) != X86::ST1) { - // We have the wrong value at st(1). Shuffle! Untested! - moveToTop(getStackEntry(1), I); - moveToTop(Op0, I); - moveToTop(RegOnTop, I); + + // FP = COPY ST. Extract fixed stack value. + // Any instruction defining ST registers must have assigned them to a + // scratch register. + if (SrcST < 8) { + unsigned DstFP = getFPReg(MO0); + assert(!isLive(DstFP) && "Cannot copy ST to live FP register"); + assert(NumPendingSTs > SrcST && "Cannot copy from dead ST register"); + unsigned SrcFP = PendingST[SrcST]; + assert(isScratchReg(SrcFP) && "Expected ST in a scratch register"); + assert(isLive(SrcFP) && "Scratch holding ST is dead"); + + // DstFP steals the stack slot from SrcFP. + unsigned Slot = getSlot(SrcFP); + Stack[Slot] = DstFP; + RegMap[DstFP] = Slot; + + // Always treat the ST as killed. + PendingST[SrcST] = NumFPRegs; + while (NumPendingSTs && PendingST[NumPendingSTs - 1] == NumFPRegs) + --NumPendingSTs; + break; } - assert(StackTop >= 2 && "Too few live registers"); - StackTop -= 2; // "Forget" both st(0) and st(1). - break; - } - case X86::MOV_Fp3232: - case X86::MOV_Fp3264: - case X86::MOV_Fp6432: - case X86::MOV_Fp6464: - case X86::MOV_Fp3280: - case X86::MOV_Fp6480: - case X86::MOV_Fp8032: - case X86::MOV_Fp8064: - case X86::MOV_Fp8080: { - const MachineOperand &MO1 = MI->getOperand(1); - unsigned SrcReg = getFPReg(MO1); - const MachineOperand &MO0 = MI->getOperand(0); - unsigned DestReg = getFPReg(MO0); - if (MI->killsRegister(X86::FP0+SrcReg)) { + // FP <- FP copy. + unsigned DstFP = getFPReg(MO0); + unsigned SrcFP = getFPReg(MO1); + assert(isLive(SrcFP) && "Cannot copy dead register"); + if (KillsSrc) { // If the input operand is killed, we can just change the owner of the // incoming stack slot into the result. - unsigned Slot = getSlot(SrcReg); - assert(Slot < 7 && DestReg < 7 && "FpMOV operands invalid!"); - Stack[Slot] = DestReg; - RegMap[DestReg] = Slot; - + unsigned Slot = getSlot(SrcFP); + Stack[Slot] = DstFP; + RegMap[DstFP] = Slot; } else { - // For FMOV we just duplicate the specified value to a new stack slot. + // For COPY we just duplicate the specified value to a new stack slot. // This could be made better, but would require substantial changes. - duplicateToTop(SrcReg, DestReg, I); + duplicateToTop(SrcFP, DstFP, I); } + break; + } + + case X86::FpPOP_RETVAL: { + // The FpPOP_RETVAL instruction is used after calls that return a value on + // the floating point stack. We cannot model this with ST defs since CALL + // instructions have fixed clobber lists. This instruction is interpreted + // to mean that there is one more live register on the stack than we + // thought. + // + // This means that StackTop does not match the hardware stack between a + // call and the FpPOP_RETVAL instructions. We do tolerate FP instructions + // between CALL and FpPOP_RETVAL as long as they don't overflow the + // hardware stack. + unsigned DstFP = getFPReg(MI->getOperand(0)); + + // Move existing stack elements up to reflect reality. + assert(StackTop < 8 && "Stack overflowed before FpPOP_RETVAL"); + if (StackTop) { + std::copy_backward(Stack, Stack + StackTop, Stack + StackTop + 1); + for (unsigned i = 0; i != NumFPRegs; ++i) + ++RegMap[i]; } + ++StackTop; + + // DstFP is the new bottom of the stack. + Stack[0] = DstFP; + RegMap[DstFP] = 0; + + // DstFP will be killed by processBasicBlock if this was a dead def. break; + } + case TargetOpcode::INLINEASM: { // The inline asm MachineInstr currently only *uses* FP registers for the // 'f' constraint. These should be turned into the current ST(x) register - // in the machine instr. Also, any kills should be explicitly popped after - // the inline asm. - unsigned Kills = 0; + // in the machine instr. + // + // There are special rules for x87 inline assembly. The compiler must know + // exactly how many registers are popped and pushed implicitly by the asm. + // Otherwise it is not possible to restore the stack state after the inline + // asm. + // + // There are 3 kinds of input operands: + // + // 1. Popped inputs. These must appear at the stack top in ST0-STn. A + // popped input operand must be in a fixed stack slot, and it is either + // tied to an output operand, or in the clobber list. The MI has ST use + // and def operands for these inputs. + // + // 2. Fixed inputs. These inputs appear in fixed stack slots, but are + // preserved by the inline asm. The fixed stack slots must be STn-STm + // following the popped inputs. A fixed input operand cannot be tied to + // an output or appear in the clobber list. The MI has ST use operands + // and no defs for these inputs. + // + // 3. Preserved inputs. These inputs use the "f" constraint which is + // represented as an FP register. The inline asm won't change these + // stack slots. + // + // Outputs must be in ST registers, FP outputs are not allowed. Clobbered + // registers do not count as output operands. The inline asm changes the + // stack as if it popped all the popped inputs and then pushed all the + // output operands. + + // Scan the assembly for ST registers used, defined and clobbered. We can + // only tell clobbers from defs by looking at the asm descriptor. + unsigned STUses = 0, STDefs = 0, STClobbers = 0, STDeadDefs = 0; + unsigned NumOps = 0; + for (unsigned i = InlineAsm::MIOp_FirstOperand, e = MI->getNumOperands(); + i != e && MI->getOperand(i).isImm(); i += 1 + NumOps) { + unsigned Flags = MI->getOperand(i).getImm(); + NumOps = InlineAsm::getNumOperandRegisters(Flags); + if (NumOps != 1) + continue; + const MachineOperand &MO = MI->getOperand(i + 1); + if (!MO.isReg()) + continue; + unsigned STReg = MO.getReg() - X86::ST0; + if (STReg >= 8) + continue; + + switch (InlineAsm::getKind(Flags)) { + case InlineAsm::Kind_RegUse: + STUses |= (1u << STReg); + break; + case InlineAsm::Kind_RegDef: + case InlineAsm::Kind_RegDefEarlyClobber: + STDefs |= (1u << STReg); + if (MO.isDead()) + STDeadDefs |= (1u << STReg); + break; + case InlineAsm::Kind_Clobber: + STClobbers |= (1u << STReg); + break; + default: + break; + } + } + + if (STUses && !isMask_32(STUses)) + report_fatal_error("Inline asm fixed inputs" + " must be last on the x87 stack"); + unsigned NumSTUses = CountTrailingOnes_32(STUses); + + // Defs must be contiguous from the stack top. ST0-STn. + if (STDefs && !isMask_32(STDefs)) + report_fatal_error("Inline asm fixed outputs" + " must be last on the x87 stack"); + unsigned NumSTDefs = CountTrailingOnes_32(STDefs); + + // So must the clobbered stack slots. ST0-STm, m >= n. + if (STClobbers && !isMask_32(STDefs | STClobbers)) + report_fatal_error("Inline asm clobbers must be last on the x87 stack"); + + // Popped inputs are the ones that are also clobbered or defined. + unsigned STPopped = STUses & (STDefs | STClobbers); + if (STPopped && !isMask_32(STPopped)) + report_fatal_error("Inline asm popped inputs" + " must be last on the x87 stack"); + unsigned NumSTPopped = CountTrailingOnes_32(STPopped); + + DEBUG(dbgs() << "Asm uses " << NumSTUses << " fixed regs, pops " + << NumSTPopped << ", and defines " << NumSTDefs << " regs.\n"); + + // Scan the instruction for FP uses corresponding to "f" constraints. + // Collect FP registers to kill afer the instruction. + // Always kill all the scratch regs. + unsigned FPKills = ((1u << NumFPRegs) - 1) & ~0xff; + unsigned FPUsed = 0; for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { MachineOperand &Op = MI->getOperand(i); if (!Op.isReg() || Op.getReg() < X86::FP0 || Op.getReg() > X86::FP6) continue; - assert(Op.isUse() && "Only handle inline asm uses right now"); - + if (!Op.isUse()) + report_fatal_error("Illegal \"f\" output constraint in inline asm"); unsigned FPReg = getFPReg(Op); - Op.setReg(getSTReg(FPReg)); - + FPUsed |= 1U << FPReg; + // If we kill this operand, make sure to pop it from the stack after the // asm. We just remember it for now, and pop them all off at the end in // a batch. if (Op.isKill()) - Kills |= 1U << FPReg; + FPKills |= 1U << FPReg; + } + + // The popped inputs will be killed by the instruction, so duplicate them + // if the FP register needs to be live after the instruction, or if it is + // used in the instruction itself. We effectively treat the popped inputs + // as early clobbers. + for (unsigned i = 0; i < NumSTPopped; ++i) { + if ((FPKills & ~FPUsed) & (1u << PendingST[i])) + continue; + unsigned SR = getScratchReg(); + duplicateToTop(PendingST[i], SR, I); + DEBUG(dbgs() << "Duplicating ST" << i << " in FP" + << unsigned(PendingST[i]) << " to avoid clobbering it.\n"); + PendingST[i] = SR; + } + + // Make sure we have a unique live register for every fixed use. Some of + // them could be undef uses, and we need to emit LD_F0 instructions. + for (unsigned i = 0; i < NumSTUses; ++i) { + if (i < NumPendingSTs && PendingST[i] < NumFPRegs) { + // Check for shared assignments. + for (unsigned j = 0; j < i; ++j) { + if (PendingST[j] != PendingST[i]) + continue; + // STi and STj are inn the same register, create a copy. + unsigned SR = getScratchReg(); + duplicateToTop(PendingST[i], SR, I); + DEBUG(dbgs() << "Duplicating ST" << i << " in FP" + << unsigned(PendingST[i]) + << " to avoid collision with ST" << j << '\n'); + PendingST[i] = SR; + } + continue; + } + unsigned SR = getScratchReg(); + DEBUG(dbgs() << "Emitting LD_F0 for ST" << i << " in FP" << SR << '\n'); + BuildMI(*MBB, I, MI->getDebugLoc(), TII->get(X86::LD_F0)); + pushReg(SR); + PendingST[i] = SR; + if (NumPendingSTs == i) + ++NumPendingSTs; + } + assert(NumPendingSTs >= NumSTUses && "Fixed registers should be assigned"); + + // Now we can rearrange the live registers to match what was requested. + shuffleStackTop(PendingST, NumPendingSTs, I); + DEBUG({dbgs() << "Before asm: "; dumpStack();}); + + // With the stack layout fixed, rewrite the FP registers. + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &Op = MI->getOperand(i); + if (!Op.isReg() || Op.getReg() < X86::FP0 || Op.getReg() > X86::FP6) + continue; + unsigned FPReg = getFPReg(Op); + Op.setReg(getSTReg(FPReg)); } + // Simulate the inline asm popping its inputs and pushing its outputs. + StackTop -= NumSTPopped; + + // Hold the fixed output registers in scratch FP registers. They will be + // transferred to real FP registers by copies. + NumPendingSTs = 0; + for (unsigned i = 0; i < NumSTDefs; ++i) { + unsigned SR = getScratchReg(); + pushReg(SR); + FPKills &= ~(1u << SR); + } + for (unsigned i = 0; i < NumSTDefs; ++i) + PendingST[NumPendingSTs++] = getStackEntry(i); + DEBUG({dbgs() << "After asm: "; dumpStack();}); + + // If any of the ST defs were dead, pop them immediately. Our caller only + // handles dead FP defs. + MachineBasicBlock::iterator InsertPt = MI; + for (unsigned i = 0; STDefs & (1u << i); ++i) { + if (!(STDeadDefs & (1u << i))) + continue; + freeStackSlotAfter(InsertPt, PendingST[i]); + PendingST[i] = NumFPRegs; + } + while (NumPendingSTs && PendingST[NumPendingSTs - 1] == NumFPRegs) + --NumPendingSTs; + // If this asm kills any FP registers (is the last use of them) we must // explicitly emit pop instructions for them. Do this now after the asm has // executed so that the ST(x) numbers are not off (which would happen if we @@ -1392,16 +1601,16 @@ void FPS::handleSpecialFP(MachineBasicBlock::iterator &I) { // // Note: this might be a non-optimal pop sequence. We might be able to do // better by trying to pop in stack order or something. - MachineBasicBlock::iterator InsertPt = MI; - while (Kills) { - unsigned FPReg = CountTrailingZeros_32(Kills); - freeStackSlotAfter(InsertPt, FPReg); - Kills &= ~(1U << FPReg); + while (FPKills) { + unsigned FPReg = CountTrailingZeros_32(FPKills); + if (isLive(FPReg)) + freeStackSlotAfter(InsertPt, FPReg); + FPKills &= ~(1U << FPReg); } // Don't delete the inline asm! return; } - + case X86::RET: case X86::RETI: // If RET has an FP register use operand, pass the first one in ST(0) and @@ -1499,33 +1708,3 @@ void FPS::handleSpecialFP(MachineBasicBlock::iterator &I) { } else --I; } - -// Translate a COPY instruction to a pseudo-op that handleSpecialFP understands. -bool FPS::translateCopy(MachineInstr *MI) { - unsigned DstReg = MI->getOperand(0).getReg(); - unsigned SrcReg = MI->getOperand(1).getReg(); - - if (DstReg == X86::ST0) { - MI->setDesc(TII->get(X86::FpSET_ST0_80)); - MI->RemoveOperand(0); - return true; - } - if (DstReg == X86::ST1) { - MI->setDesc(TII->get(X86::FpSET_ST1_80)); - MI->RemoveOperand(0); - return true; - } - if (SrcReg == X86::ST0) { - MI->setDesc(TII->get(X86::FpGET_ST0_80)); - return true; - } - if (SrcReg == X86::ST1) { - MI->setDesc(TII->get(X86::FpGET_ST1_80)); - return true; - } - if (X86::RFP80RegClass.contains(DstReg, SrcReg)) { - MI->setDesc(TII->get(X86::MOV_Fp8080)); - return true; - } - return false; -} diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 0810267..b327f1b 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -1511,20 +1511,15 @@ X86TargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag, // If this is a call to a function that returns an fp value on the floating // point stack, we must guarantee the the value is popped from the stack, so // a CopyFromReg is not good enough - the copy instruction may be eliminated - // if the return value is not used. We use the FpGET_ST0 instructions + // if the return value is not used. We use the FpPOP_RETVAL instruction // instead. if (VA.getLocReg() == X86::ST0 || VA.getLocReg() == X86::ST1) { // If we prefer to use the value in xmm registers, copy it out as f80 and // use a truncate to move it from fp stack reg to xmm reg. if (isScalarFPTypeInSSEReg(VA.getValVT())) CopyVT = MVT::f80; - bool isST0 = VA.getLocReg() == X86::ST0; - unsigned Opc = 0; - if (CopyVT == MVT::f32) Opc = isST0 ? X86::FpGET_ST0_32:X86::FpGET_ST1_32; - if (CopyVT == MVT::f64) Opc = isST0 ? X86::FpGET_ST0_64:X86::FpGET_ST1_64; - if (CopyVT == MVT::f80) Opc = isST0 ? X86::FpGET_ST0_80:X86::FpGET_ST1_80; SDValue Ops[] = { Chain, InFlag }; - Chain = SDValue(DAG.getMachineNode(Opc, dl, CopyVT, MVT::Other, MVT::Glue, - Ops, 2), 1); + Chain = SDValue(DAG.getMachineNode(X86::FpPOP_RETVAL, dl, CopyVT, + MVT::Other, MVT::Glue, Ops, 2), 1); Val = Chain.getValue(0); // Round the f80 to the right size, which also moves it to the appropriate diff --git a/lib/Target/X86/X86InstrFPStack.td b/lib/Target/X86/X86InstrFPStack.td index b506f5e..7cb870f 100644 --- a/lib/Target/X86/X86InstrFPStack.td +++ b/lib/Target/X86/X86InstrFPStack.td @@ -112,31 +112,8 @@ let usesCustomInserter = 1 in { // Expanded after instruction selection. // a pattern) and the FPI instruction should have emission info (e.g. opcode // encoding and asm printing info). -// Pseudo Instructions for FP stack return values. -def FpGET_ST0_32 : FpI_<(outs RFP32:$dst), (ins), SpecialFP, []>; // FPR = ST(0) -def FpGET_ST0_64 : FpI_<(outs RFP64:$dst), (ins), SpecialFP, []>; // FPR = ST(0) -def FpGET_ST0_80 : FpI_<(outs RFP80:$dst), (ins), SpecialFP, []>; // FPR = ST(0) - -// FpGET_ST1* should only be issued *after* an FpGET_ST0* has been issued when -// there are two values live out on the stack from a call or inlineasm. This -// magic is handled by the stackifier. It is not valid to emit FpGET_ST1* and -// then FpGET_ST0*. In addition, it is invalid for any FP-using operations to -// occur between them. -def FpGET_ST1_32 : FpI_<(outs RFP32:$dst), (ins), SpecialFP, []>; // FPR = ST(1) -def FpGET_ST1_64 : FpI_<(outs RFP64:$dst), (ins), SpecialFP, []>; // FPR = ST(1) -def FpGET_ST1_80 : FpI_<(outs RFP80:$dst), (ins), SpecialFP, []>; // FPR = ST(1) - -let Defs = [ST0] in { -def FpSET_ST0_32 : FpI_<(outs), (ins RFP32:$src), SpecialFP, []>; // ST(0) = FPR -def FpSET_ST0_64 : FpI_<(outs), (ins RFP64:$src), SpecialFP, []>; // ST(0) = FPR -def FpSET_ST0_80 : FpI_<(outs), (ins RFP80:$src), SpecialFP, []>; // ST(0) = FPR -} - -let Defs = [ST1] in { -def FpSET_ST1_32 : FpI_<(outs), (ins RFP32:$src), SpecialFP, []>; // ST(1) = FPR -def FpSET_ST1_64 : FpI_<(outs), (ins RFP64:$src), SpecialFP, []>; // ST(1) = FPR -def FpSET_ST1_80 : FpI_<(outs), (ins RFP80:$src), SpecialFP, []>; // ST(1) = FPR -} +// Pseudo Instruction for FP stack return values. +def FpPOP_RETVAL : FpI_<(outs RFP80:$dst), (ins), SpecialFP, []>; // FpIf32, FpIf64 - Floating Point Pseudo Instruction template. // f32 instructions can use SSE1 and are predicated on FPStackf32 == !SSE1. @@ -147,19 +124,6 @@ class FpIf32 pattern> : class FpIf64 pattern> : FpI_, Requires<[FPStackf64]>; -// Register copies. Just copies, the shortening ones do not truncate. -let neverHasSideEffects = 1 in { - def MOV_Fp3232 : FpIf32<(outs RFP32:$dst), (ins RFP32:$src), SpecialFP, []>; - def MOV_Fp3264 : FpIf32<(outs RFP64:$dst), (ins RFP32:$src), SpecialFP, []>; - def MOV_Fp6432 : FpIf32<(outs RFP32:$dst), (ins RFP64:$src), SpecialFP, []>; - def MOV_Fp6464 : FpIf64<(outs RFP64:$dst), (ins RFP64:$src), SpecialFP, []>; - def MOV_Fp8032 : FpIf32<(outs RFP32:$dst), (ins RFP80:$src), SpecialFP, []>; - def MOV_Fp3280 : FpIf32<(outs RFP80:$dst), (ins RFP32:$src), SpecialFP, []>; - def MOV_Fp8064 : FpIf64<(outs RFP64:$dst), (ins RFP80:$src), SpecialFP, []>; - def MOV_Fp6480 : FpIf64<(outs RFP80:$dst), (ins RFP64:$src), SpecialFP, []>; - def MOV_Fp8080 : FpI_ <(outs RFP80:$dst), (ins RFP80:$src), SpecialFP, []>; -} - // Factoring for arithmetic. multiclass FPBinary_rr { // Register op register -> register diff --git a/lib/Target/X86/X86RegisterInfo.cpp b/lib/Target/X86/X86RegisterInfo.cpp index 48f60f8..9e4fdad 100644 --- a/lib/Target/X86/X86RegisterInfo.cpp +++ b/lib/Target/X86/X86RegisterInfo.cpp @@ -500,18 +500,6 @@ BitVector X86RegisterInfo::getReservedRegs(const MachineFunction &MF) const { Reserved.set(X86::BPL); } - // Mark the x87 stack registers as reserved, since they don't behave normally - // with respect to liveness. We don't fully model the effects of x87 stack - // pushes and pops after stackification. - Reserved.set(X86::ST0); - Reserved.set(X86::ST1); - Reserved.set(X86::ST2); - Reserved.set(X86::ST3); - Reserved.set(X86::ST4); - Reserved.set(X86::ST5); - Reserved.set(X86::ST6); - Reserved.set(X86::ST7); - // Mark the segment registers as reserved. Reserved.set(X86::CS); Reserved.set(X86::SS); diff --git a/lib/Target/X86/X86RegisterInfo.td b/lib/Target/X86/X86RegisterInfo.td index 14d6d64..203722a 100644 --- a/lib/Target/X86/X86RegisterInfo.td +++ b/lib/Target/X86/X86RegisterInfo.td @@ -206,15 +206,22 @@ let Namespace = "X86" in { def YMM15: RegisterWithSubRegs<"ymm15", [XMM15]>, DwarfRegAlias; } - // Floating point stack registers - def ST0 : Register<"st(0)">, DwarfRegNum<[33, 12, 11]>; - def ST1 : Register<"st(1)">, DwarfRegNum<[34, 13, 12]>; - def ST2 : Register<"st(2)">, DwarfRegNum<[35, 14, 13]>; - def ST3 : Register<"st(3)">, DwarfRegNum<[36, 15, 14]>; - def ST4 : Register<"st(4)">, DwarfRegNum<[37, 16, 15]>; - def ST5 : Register<"st(5)">, DwarfRegNum<[38, 17, 16]>; - def ST6 : Register<"st(6)">, DwarfRegNum<[39, 18, 17]>; - def ST7 : Register<"st(7)">, DwarfRegNum<[40, 19, 18]>; + class STRegister A> : Register { + let Aliases = A; + } + + // Floating point stack registers. These don't map one-to-one to the FP + // pseudo registers, but we still mark them as aliasing FP registers. That + // way both kinds can be live without exceeding the stack depth. ST registers + // are only live around inline assembly. + def ST0 : STRegister<"st(0)", []>, DwarfRegNum<[33, 12, 11]>; + def ST1 : STRegister<"st(1)", [FP6]>, DwarfRegNum<[34, 13, 12]>; + def ST2 : STRegister<"st(2)", [FP5]>, DwarfRegNum<[35, 14, 13]>; + def ST3 : STRegister<"st(3)", [FP4]>, DwarfRegNum<[36, 15, 14]>; + def ST4 : STRegister<"st(4)", [FP3]>, DwarfRegNum<[37, 16, 15]>; + def ST5 : STRegister<"st(5)", [FP2]>, DwarfRegNum<[38, 17, 16]>; + def ST6 : STRegister<"st(6)", [FP1]>, DwarfRegNum<[39, 18, 17]>; + def ST7 : STRegister<"st(7)", [FP0]>, DwarfRegNum<[40, 19, 18]>; // Status flags register def EFLAGS : Register<"flags">; diff --git a/test/CodeGen/X86/inline-asm-fpstack.ll b/test/CodeGen/X86/inline-asm-fpstack.ll index d15f7ff..8e48bbe 100644 --- a/test/CodeGen/X86/inline-asm-fpstack.ll +++ b/test/CodeGen/X86/inline-asm-fpstack.ll @@ -106,6 +106,25 @@ return: ret void } +; Passing a non-killed value through asm in {st}. +; Make sure it is not duped before. +; Second asm kills st(0), so we shouldn't pop anything +; CHECK: testPR4185b +; CHECK-NOT: fld %st(0) +; CHECK: fistl +; CHECK-NOT: fstp +; CHECK: fistpl +; CHECK-NOT: fstp +; CHECK: ret +; A valid alternative would be to remat the constant pool load before each +; inline asm. +define void @testPR4185b() { +return: + call void asm sideeffect "fistl $0", "{st}"(double 1.000000e+06) + call void asm sideeffect "fistpl $0", "{st},~{st}"(double 1.000000e+06) + ret void +} + ; PR4459 ; The return value from ceil must be duped before being consumed by asm. ; CHECK: testPR4459 @@ -160,3 +179,153 @@ entry: tail call void asm sideeffect "fistpl $0", "{st},~{st}"(x86_fp80 %5) ret void } + +; An input argument in a fixed position is implicitly popped by the asm only if +; the input argument is tied to an output register, or it is in the clobber list. +; The clobber list case is tested above. +; +; This doesn't implicitly pop the stack: +; +; void fist1(long double x, int *p) { +; asm volatile ("fistl %1" : : "t"(x), "m"(*p)); +; } +; +; CHECK: fist1 +; CHECK: fldt +; CHECK: fistl (%e +; CHECK: fstp +; CHECK: ret +define void @fist1(x86_fp80 %x, i32* %p) nounwind ssp { +entry: + tail call void asm sideeffect "fistl $1", "{st},*m,~{memory},~{dirflag},~{fpsr},~{flags}"(x86_fp80 %x, i32* %p) nounwind + ret void +} + +; Here, the input operand is tied to an output which means that is is +; implicitly popped (and then the output is implicitly pushed). +; +; long double fist2(long double x, int *p) { +; long double y; +; asm ("fistl %1" : "=&t"(y) : "0"(x), "m"(*p) : "memory"); +; return y; +; } +; +; CHECK: fist2 +; CHECK: fldt +; CHECK: fistl (%e +; CHECK-NOT: fstp +; CHECK: ret +define x86_fp80 @fist2(x86_fp80 %x, i32* %p) nounwind ssp { +entry: + %0 = tail call x86_fp80 asm "fistl $2", "=&{st},0,*m,~{memory},~{dirflag},~{fpsr},~{flags}"(x86_fp80 %x, i32* %p) nounwind + ret x86_fp80 %0 +} + +; An 'f' constraint is never implicitly popped: +; +; void fucomp1(long double x, long double y) { +; asm volatile ("fucomp %1" : : "t"(x), "f"(y) : "st"); +; } +; CHECK: fucomp1 +; CHECK: fldt +; CHECK: fldt +; CHECK: fucomp %st +; CHECK: fstp +; CHECK-NOT: fstp +; CHECK: ret +define void @fucomp1(x86_fp80 %x, x86_fp80 %y) nounwind ssp { +entry: + tail call void asm sideeffect "fucomp $1", "{st},f,~{st},~{dirflag},~{fpsr},~{flags}"(x86_fp80 %x, x86_fp80 %y) nounwind + ret void +} + +; The 'u' constraint is only popped implicitly when clobbered: +; +; void fucomp2(long double x, long double y) { +; asm volatile ("fucomp %1" : : "t"(x), "u"(y) : "st"); +; } +; +; void fucomp3(long double x, long double y) { +; asm volatile ("fucompp %1" : : "t"(x), "u"(y) : "st", "st(1)"); +; } +; +; CHECK: fucomp2 +; CHECK: fldt +; CHECK: fldt +; CHECK: fucomp %st(1) +; CHECK: fstp +; CHECK-NOT: fstp +; CHECK: ret +; +; CHECK: fucomp3 +; CHECK: fldt +; CHECK: fldt +; CHECK: fucompp %st(1) +; CHECK-NOT: fstp +; CHECK: ret +define void @fucomp2(x86_fp80 %x, x86_fp80 %y) nounwind ssp { +entry: + tail call void asm sideeffect "fucomp $1", "{st},{st(1)},~{st},~{dirflag},~{fpsr},~{flags}"(x86_fp80 %x, x86_fp80 %y) nounwind + ret void +} +define void @fucomp3(x86_fp80 %x, x86_fp80 %y) nounwind ssp { +entry: + tail call void asm sideeffect "fucompp $1", "{st},{st(1)},~{st},~{st(1)},~{dirflag},~{fpsr},~{flags}"(x86_fp80 %x, x86_fp80 %y) nounwind + ret void +} + +; One input, two outputs, one dead output. +%complex = type { float, float } +; CHECK: sincos1 +; CHECK: flds +; CHECK-NOT: fxch +; CHECK: sincos +; CHECK-NOT: fstp +; CHECK: fstp %st(1) +; CHECK-NOT: fstp +; CHECK: ret +define float @sincos1(float %x) nounwind ssp { +entry: + %0 = tail call %complex asm "sincos", "={st},={st(1)},0,~{dirflag},~{fpsr},~{flags}"(float %x) nounwind + %asmresult = extractvalue %complex %0, 0 + ret float %asmresult +} + +; Same thing, swapped output operands. +; CHECK: sincos2 +; CHECK: flds +; CHECK-NOT: fxch +; CHECK: sincos +; CHECK-NOT: fstp +; CHECK: fstp %st(1) +; CHECK-NOT: fstp +; CHECK: ret +define float @sincos2(float %x) nounwind ssp { +entry: + %0 = tail call %complex asm "sincos", "={st(1)},={st},1,~{dirflag},~{fpsr},~{flags}"(float %x) nounwind + %asmresult = extractvalue %complex %0, 1 + ret float %asmresult +} + +; Clobber st(0) after it was live-out/dead from the previous asm. +; CHECK: sincos3 +; Load x, make a copy for the second asm. +; CHECK: flds +; CHECK: fld %st(0) +; CHECK: sincos +; Discard dead result in st(0), bring x to the top. +; CHECK: fstp %st(0) +; CHECK: fxch +; x is now in st(0) for the second asm +; CHECK: sincos +; Discard both results. +; CHECK: fstp +; CHECK: fstp +; CHECK: ret +define float @sincos3(float %x) nounwind ssp { +entry: + %0 = tail call %complex asm sideeffect "sincos", "={st(1)},={st},1,~{dirflag},~{fpsr},~{flags}"(float %x) nounwind + %1 = tail call %complex asm sideeffect "sincos", "={st(1)},={st},1,~{dirflag},~{fpsr},~{flags}"(float %x) nounwind + %asmresult = extractvalue %complex %0, 0 + ret float %asmresult +} -- cgit v1.1 From e837dead3c8dc3445ef6a0e2322179c57e264a13 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Tue, 28 Jun 2011 19:10:37 +0000 Subject: - Rename TargetInstrDesc, TargetOperandInfo to MCInstrDesc and MCOperandInfo and sink them into MC layer. - Added MCInstrInfo, which captures the tablegen generated static data. Chang TargetInstrInfo so it's based off MCInstrInfo. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134021 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CodeGen/MachineFunction.h | 2 +- include/llvm/CodeGen/MachineInstr.h | 29 +- include/llvm/CodeGen/MachineInstrBuilder.h | 26 +- include/llvm/CodeGen/ScheduleDAG.h | 10 +- include/llvm/CodeGen/ScoreboardHazardRecognizer.h | 1 - include/llvm/MC/MCInstrDesc.h | 489 ++++++++++++++++++++ include/llvm/MC/MCInstrInfo.h | 51 +++ include/llvm/MC/MCRegisterInfo.h | 2 +- include/llvm/Target/TargetInstrDesc.h | 493 --------------------- include/llvm/Target/TargetInstrInfo.h | 23 +- include/llvm/Target/TargetRegisterInfo.h | 2 +- lib/CodeGen/BranchFolding.cpp | 6 +- lib/CodeGen/ExpandISelPseudos.cpp | 4 +- lib/CodeGen/IfConversion.cpp | 10 +- lib/CodeGen/MachineBasicBlock.cpp | 1 - lib/CodeGen/MachineCSE.cpp | 6 +- lib/CodeGen/MachineFunction.cpp | 4 +- lib/CodeGen/MachineInstr.cpp | 110 ++--- lib/CodeGen/MachineLICM.cpp | 6 +- lib/CodeGen/MachineVerifier.cpp | 37 +- lib/CodeGen/PeepholeOptimizer.cpp | 12 +- lib/CodeGen/RegAllocFast.cpp | 14 +- lib/CodeGen/RegisterCoalescer.cpp | 18 +- lib/CodeGen/ScheduleDAG.cpp | 2 +- lib/CodeGen/ScheduleDAGInstrs.cpp | 32 +- lib/CodeGen/ScoreboardHazardRecognizer.cpp | 14 +- lib/CodeGen/SelectionDAG/FastISel.cpp | 22 +- lib/CodeGen/SelectionDAG/InstrEmitter.cpp | 32 +- lib/CodeGen/SelectionDAG/InstrEmitter.h | 8 +- lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp | 22 +- lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp | 40 +- lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp | 14 +- lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 12 +- lib/CodeGen/StackSlotColoring.cpp | 8 +- lib/CodeGen/TailDuplication.cpp | 4 +- lib/CodeGen/TargetInstrInfoImpl.cpp | 24 +- lib/CodeGen/TwoAddressInstructionPass.cpp | 33 +- lib/CodeGen/VirtRegRewriter.cpp | 20 +- lib/Target/ARM/ARMBaseInstrInfo.cpp | 112 ++--- lib/Target/ARM/ARMBaseInstrInfo.h | 12 +- lib/Target/ARM/ARMBaseRegisterInfo.cpp | 10 +- lib/Target/ARM/ARMCodeEmitter.cpp | 150 +++---- lib/Target/ARM/ARMConstantIslandPass.cpp | 12 +- lib/Target/ARM/ARMExpandPseudoInsts.cpp | 2 +- lib/Target/ARM/ARMFastISel.cpp | 30 +- lib/Target/ARM/ARMHazardRecognizer.cpp | 20 +- lib/Target/ARM/ARMISelDAGToDAG.cpp | 6 +- lib/Target/ARM/ARMISelLowering.cpp | 6 +- lib/Target/ARM/ARMLoadStoreOptimizer.cpp | 22 +- lib/Target/ARM/ARMMCCodeEmitter.cpp | 2 +- .../ARM/Disassembler/ARMDisassemblerCore.cpp | 166 +++---- .../ARM/Disassembler/ThumbDisassemblerCore.h | 78 ++-- lib/Target/ARM/MLxExpansionPass.cpp | 26 +- lib/Target/ARM/Thumb1RegisterInfo.cpp | 16 +- lib/Target/ARM/Thumb2InstrInfo.cpp | 2 +- lib/Target/ARM/Thumb2SizeReduction.cpp | 68 +-- lib/Target/Blackfin/BlackfinISelDAGToDAG.cpp | 12 +- lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp | 6 +- lib/Target/MBlaze/MBlazeMCCodeEmitter.cpp | 2 +- lib/Target/MSP430/MSP430InstrInfo.cpp | 10 +- lib/Target/Mips/MipsDelaySlotFiller.cpp | 6 +- lib/Target/Mips/MipsExpandPseudo.cpp | 8 +- lib/Target/Mips/MipsInstrInfo.cpp | 4 +- lib/Target/PTX/PTXInstrInfo.cpp | 14 +- lib/Target/PowerPC/PPCHazardRecognizers.cpp | 8 +- lib/Target/PowerPC/PPCInstrInfo.cpp | 10 +- lib/Target/Sparc/DelaySlotFiller.cpp | 2 +- lib/Target/SystemZ/SystemZInstrBuilder.h | 6 +- lib/Target/SystemZ/SystemZInstrInfo.cpp | 12 +- lib/Target/SystemZ/SystemZInstrInfo.h | 6 +- lib/Target/TargetInstrInfo.cpp | 21 +- lib/Target/X86/X86CodeEmitter.cpp | 14 +- lib/Target/X86/X86FastISel.cpp | 2 +- lib/Target/X86/X86InstrBuilder.h | 6 +- lib/Target/X86/X86InstrInfo.cpp | 32 +- lib/Target/X86/X86MCCodeEmitter.cpp | 18 +- utils/TableGen/InstrInfoEmitter.cpp | 66 +-- utils/TableGen/InstrInfoEmitter.h | 4 - 78 files changed, 1340 insertions(+), 1312 deletions(-) create mode 100644 include/llvm/MC/MCInstrDesc.h create mode 100644 include/llvm/MC/MCInstrInfo.h delete mode 100644 include/llvm/Target/TargetInstrDesc.h diff --git a/include/llvm/CodeGen/MachineFunction.h b/include/llvm/CodeGen/MachineFunction.h index f56c053..6e08f7b 100644 --- a/include/llvm/CodeGen/MachineFunction.h +++ b/include/llvm/CodeGen/MachineFunction.h @@ -345,7 +345,7 @@ public: /// CreateMachineInstr - Allocate a new MachineInstr. Use this instead /// of `new MachineInstr'. /// - MachineInstr *CreateMachineInstr(const TargetInstrDesc &TID, + MachineInstr *CreateMachineInstr(const MCInstrDesc &MCID, DebugLoc DL, bool NoImp = false); diff --git a/include/llvm/CodeGen/MachineInstr.h b/include/llvm/CodeGen/MachineInstr.h index c36dd69..07a14cf 100644 --- a/include/llvm/CodeGen/MachineInstr.h +++ b/include/llvm/CodeGen/MachineInstr.h @@ -17,7 +17,7 @@ #define LLVM_CODEGEN_MACHINEINSTR_H #include "llvm/CodeGen/MachineOperand.h" -#include "llvm/Target/TargetInstrDesc.h" +#include "llvm/MC/MCInstrDesc.h" #include "llvm/Target/TargetOpcodes.h" #include "llvm/ADT/ilist.h" #include "llvm/ADT/ilist_node.h" @@ -30,7 +30,6 @@ namespace llvm { template class SmallVectorImpl; class AliasAnalysis; -class TargetInstrDesc; class TargetInstrInfo; class TargetRegisterInfo; class MachineFunction; @@ -57,7 +56,7 @@ public: // function frame setup code. }; private: - const TargetInstrDesc *TID; // Instruction descriptor. + const MCInstrDesc *MCID; // Instruction descriptor. uint16_t NumImplicitOps; // Number of implicit operands (which // are determined at construction time). @@ -94,7 +93,7 @@ private: MachineInstr(MachineFunction &, const MachineInstr &); /// MachineInstr ctor - This constructor creates a dummy MachineInstr with - /// TID NULL and no operands. + /// MCID NULL and no operands. MachineInstr(); // The next two constructors have DebugLoc and non-DebugLoc versions; @@ -103,25 +102,25 @@ private: /// MachineInstr ctor - This constructor creates a MachineInstr and adds the /// implicit operands. It reserves space for the number of operands specified - /// by the TargetInstrDesc. The version with a DebugLoc should be preferred. - explicit MachineInstr(const TargetInstrDesc &TID, bool NoImp = false); + /// by the MCInstrDesc. The version with a DebugLoc should be preferred. + explicit MachineInstr(const MCInstrDesc &MCID, bool NoImp = false); /// MachineInstr ctor - Work exactly the same as the ctor above, except that /// the MachineInstr is created and added to the end of the specified basic /// block. The version with a DebugLoc should be preferred. - MachineInstr(MachineBasicBlock *MBB, const TargetInstrDesc &TID); + MachineInstr(MachineBasicBlock *MBB, const MCInstrDesc &MCID); /// MachineInstr ctor - This constructor create a MachineInstr and add the /// implicit operands. It reserves space for number of operands specified by - /// TargetInstrDesc. An explicit DebugLoc is supplied. - explicit MachineInstr(const TargetInstrDesc &TID, const DebugLoc dl, + /// MCInstrDesc. An explicit DebugLoc is supplied. + explicit MachineInstr(const MCInstrDesc &MCID, const DebugLoc dl, bool NoImp = false); /// MachineInstr ctor - Work exactly the same as the ctor above, except that /// the MachineInstr is created and added to the end of the specified basic /// block. MachineInstr(MachineBasicBlock *MBB, const DebugLoc dl, - const TargetInstrDesc &TID); + const MCInstrDesc &MCID); ~MachineInstr(); @@ -183,11 +182,11 @@ public: /// getDesc - Returns the target instruction descriptor of this /// MachineInstr. - const TargetInstrDesc &getDesc() const { return *TID; } + const MCInstrDesc &getDesc() const { return *MCID; } /// getOpcode - Returns the opcode of this MachineInstr. /// - int getOpcode() const { return TID->Opcode; } + int getOpcode() const { return MCID->Opcode; } /// Access to explicit operands of the instruction. /// @@ -464,8 +463,8 @@ public: /// hasUnmodeledSideEffects - Return true if this instruction has side /// effects that are not modeled by mayLoad / mayStore, etc. - /// For all instructions, the property is encoded in TargetInstrDesc::Flags - /// (see TargetInstrDesc::hasUnmodeledSideEffects(). The only exception is + /// For all instructions, the property is encoded in MCInstrDesc::Flags + /// (see MCInstrDesc::hasUnmodeledSideEffects(). The only exception is /// INLINEASM instruction, in which case the side effect property is encoded /// in one of its operands (see InlineAsm::Extra_HasSideEffect). /// @@ -497,7 +496,7 @@ public: /// setDesc - Replace the instruction descriptor (thus opcode) of /// the current instruction with a new one. /// - void setDesc(const TargetInstrDesc &tid) { TID = &tid; } + void setDesc(const MCInstrDesc &tid) { MCID = &tid; } /// setDebugLoc - Replace current source information with new such. /// Avoid using this, the constructor argument is preferable. diff --git a/include/llvm/CodeGen/MachineInstrBuilder.h b/include/llvm/CodeGen/MachineInstrBuilder.h index 1c48af9..b989027 100644 --- a/include/llvm/CodeGen/MachineInstrBuilder.h +++ b/include/llvm/CodeGen/MachineInstrBuilder.h @@ -22,7 +22,7 @@ namespace llvm { -class TargetInstrDesc; +class MCInstrDesc; class MDNode; namespace RegState { @@ -180,8 +180,8 @@ public: /// inline MachineInstrBuilder BuildMI(MachineFunction &MF, DebugLoc DL, - const TargetInstrDesc &TID) { - return MachineInstrBuilder(MF.CreateMachineInstr(TID, DL)); + const MCInstrDesc &MCID) { + return MachineInstrBuilder(MF.CreateMachineInstr(MCID, DL)); } /// BuildMI - This version of the builder sets up the first operand as a @@ -189,9 +189,9 @@ inline MachineInstrBuilder BuildMI(MachineFunction &MF, /// inline MachineInstrBuilder BuildMI(MachineFunction &MF, DebugLoc DL, - const TargetInstrDesc &TID, + const MCInstrDesc &MCID, unsigned DestReg) { - return MachineInstrBuilder(MF.CreateMachineInstr(TID, DL)) + return MachineInstrBuilder(MF.CreateMachineInstr(MCID, DL)) .addReg(DestReg, RegState::Define); } @@ -202,9 +202,9 @@ inline MachineInstrBuilder BuildMI(MachineFunction &MF, inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, MachineBasicBlock::iterator I, DebugLoc DL, - const TargetInstrDesc &TID, + const MCInstrDesc &MCID, unsigned DestReg) { - MachineInstr *MI = BB.getParent()->CreateMachineInstr(TID, DL); + MachineInstr *MI = BB.getParent()->CreateMachineInstr(MCID, DL); BB.insert(I, MI); return MachineInstrBuilder(MI).addReg(DestReg, RegState::Define); } @@ -216,8 +216,8 @@ inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, MachineBasicBlock::iterator I, DebugLoc DL, - const TargetInstrDesc &TID) { - MachineInstr *MI = BB.getParent()->CreateMachineInstr(TID, DL); + const MCInstrDesc &MCID) { + MachineInstr *MI = BB.getParent()->CreateMachineInstr(MCID, DL); BB.insert(I, MI); return MachineInstrBuilder(MI); } @@ -228,8 +228,8 @@ inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, /// inline MachineInstrBuilder BuildMI(MachineBasicBlock *BB, DebugLoc DL, - const TargetInstrDesc &TID) { - return BuildMI(*BB, BB->end(), DL, TID); + const MCInstrDesc &MCID) { + return BuildMI(*BB, BB->end(), DL, MCID); } /// BuildMI - This version of the builder inserts the newly-built @@ -238,9 +238,9 @@ inline MachineInstrBuilder BuildMI(MachineBasicBlock *BB, /// inline MachineInstrBuilder BuildMI(MachineBasicBlock *BB, DebugLoc DL, - const TargetInstrDesc &TID, + const MCInstrDesc &MCID, unsigned DestReg) { - return BuildMI(*BB, BB->end(), DL, TID, DestReg); + return BuildMI(*BB, BB->end(), DL, MCID, DestReg); } inline unsigned getDefRegState(bool B) { diff --git a/include/llvm/CodeGen/ScheduleDAG.h b/include/llvm/CodeGen/ScheduleDAG.h index 0657664..1bbc6c5 100644 --- a/include/llvm/CodeGen/ScheduleDAG.h +++ b/include/llvm/CodeGen/ScheduleDAG.h @@ -34,7 +34,7 @@ namespace llvm { class ScheduleDAG; class SDNode; class TargetInstrInfo; - class TargetInstrDesc; + class MCInstrDesc; class TargetMachine; class TargetRegisterClass; template class GraphWriter; @@ -507,9 +507,9 @@ namespace llvm { virtual ~ScheduleDAG(); - /// getInstrDesc - Return the TargetInstrDesc of this SUnit. + /// getInstrDesc - Return the MCInstrDesc of this SUnit. /// Return NULL for SDNodes without a machine opcode. - const TargetInstrDesc *getInstrDesc(const SUnit *SU) const { + const MCInstrDesc *getInstrDesc(const SUnit *SU) const { if (SU->isInstr()) return &SU->getInstr()->getDesc(); return getNodeDesc(SU->getNode()); } @@ -579,8 +579,8 @@ namespace llvm { void EmitPhysRegCopy(SUnit *SU, DenseMap &VRBaseMap); private: - // Return the TargetInstrDesc of this SDNode or NULL. - const TargetInstrDesc *getNodeDesc(const SDNode *Node) const; + // Return the MCInstrDesc of this SDNode or NULL. + const MCInstrDesc *getNodeDesc(const SDNode *Node) const; }; class SUnitIterator : public std::iterator> Pos) & 0xf; + } + return -1; + } + + /// getOpcode - Return the opcode number for this descriptor. + unsigned getOpcode() const { + return Opcode; + } + + /// getName - Return the name of the record in the .td file for this + /// instruction, for example "ADD8ri". + const char *getName() const { + return Name; + } + + /// getNumOperands - Return the number of declared MachineOperands for this + /// MachineInstruction. Note that variadic (isVariadic() returns true) + /// instructions may have additional operands at the end of the list, and note + /// that the machine instruction may include implicit register def/uses as + /// well. + unsigned getNumOperands() const { + return NumOperands; + } + + /// getNumDefs - Return the number of MachineOperands that are register + /// definitions. Register definitions always occur at the start of the + /// machine operand list. This is the number of "outs" in the .td file, + /// and does not include implicit defs. + unsigned getNumDefs() const { + return NumDefs; + } + + /// isVariadic - Return true if this instruction can have a variable number of + /// operands. In this case, the variable operands will be after the normal + /// operands but before the implicit definitions and uses (if any are + /// present). + bool isVariadic() const { + return Flags & (1 << MCID::Variadic); + } + + /// hasOptionalDef - Set if this instruction has an optional definition, e.g. + /// ARM instructions which can set condition code if 's' bit is set. + bool hasOptionalDef() const { + return Flags & (1 << MCID::HasOptionalDef); + } + + /// getImplicitUses - Return a list of registers that are potentially + /// read by any instance of this machine instruction. For example, on X86, + /// the "adc" instruction adds two register operands and adds the carry bit in + /// from the flags register. In this case, the instruction is marked as + /// implicitly reading the flags. Likewise, the variable shift instruction on + /// X86 is marked as implicitly reading the 'CL' register, which it always + /// does. + /// + /// This method returns null if the instruction has no implicit uses. + const unsigned *getImplicitUses() const { + return ImplicitUses; + } + + /// getNumImplicitUses - Return the number of implicit uses this instruction + /// has. + unsigned getNumImplicitUses() const { + if (ImplicitUses == 0) return 0; + unsigned i = 0; + for (; ImplicitUses[i]; ++i) /*empty*/; + return i; + } + + /// getImplicitDefs - Return a list of registers that are potentially + /// written by any instance of this machine instruction. For example, on X86, + /// many instructions implicitly set the flags register. In this case, they + /// are marked as setting the FLAGS. Likewise, many instructions always + /// deposit their result in a physical register. For example, the X86 divide + /// instruction always deposits the quotient and remainder in the EAX/EDX + /// registers. For that instruction, this will return a list containing the + /// EAX/EDX/EFLAGS registers. + /// + /// This method returns null if the instruction has no implicit defs. + const unsigned *getImplicitDefs() const { + return ImplicitDefs; + } + + /// getNumImplicitDefs - Return the number of implicit defs this instruction + /// has. + unsigned getNumImplicitDefs() const { + if (ImplicitDefs == 0) return 0; + unsigned i = 0; + for (; ImplicitDefs[i]; ++i) /*empty*/; + return i; + } + + /// hasImplicitUseOfPhysReg - Return true if this instruction implicitly + /// uses the specified physical register. + bool hasImplicitUseOfPhysReg(unsigned Reg) const { + if (const unsigned *ImpUses = ImplicitUses) + for (; *ImpUses; ++ImpUses) + if (*ImpUses == Reg) return true; + return false; + } + + /// hasImplicitDefOfPhysReg - Return true if this instruction implicitly + /// defines the specified physical register. + bool hasImplicitDefOfPhysReg(unsigned Reg) const { + if (const unsigned *ImpDefs = ImplicitDefs) + for (; *ImpDefs; ++ImpDefs) + if (*ImpDefs == Reg) return true; + return false; + } + + /// getSchedClass - Return the scheduling class for this instruction. The + /// scheduling class is an index into the InstrItineraryData table. This + /// returns zero if there is no known scheduling information for the + /// instruction. + /// + unsigned getSchedClass() const { + return SchedClass; + } + + bool isReturn() const { + return Flags & (1 << MCID::Return); + } + + bool isCall() const { + return Flags & (1 << MCID::Call); + } + + /// isBarrier - Returns true if the specified instruction stops control flow + /// from executing the instruction immediately following it. Examples include + /// unconditional branches and return instructions. + bool isBarrier() const { + return Flags & (1 << MCID::Barrier); + } + + /// isTerminator - Returns true if this instruction part of the terminator for + /// a basic block. Typically this is things like return and branch + /// instructions. + /// + /// Various passes use this to insert code into the bottom of a basic block, + /// but before control flow occurs. + bool isTerminator() const { + return Flags & (1 << MCID::Terminator); + } + + /// isBranch - Returns true if this is a conditional, unconditional, or + /// indirect branch. Predicates below can be used to discriminate between + /// these cases, and the TargetInstrInfo::AnalyzeBranch method can be used to + /// get more information. + bool isBranch() const { + return Flags & (1 << MCID::Branch); + } + + /// isIndirectBranch - Return true if this is an indirect branch, such as a + /// branch through a register. + bool isIndirectBranch() const { + return Flags & (1 << MCID::IndirectBranch); + } + + /// isConditionalBranch - Return true if this is a branch which may fall + /// through to the next instruction or may transfer control flow to some other + /// block. The TargetInstrInfo::AnalyzeBranch method can be used to get more + /// information about this branch. + bool isConditionalBranch() const { + return isBranch() & !isBarrier() & !isIndirectBranch(); + } + + /// isUnconditionalBranch - Return true if this is a branch which always + /// transfers control flow to some other block. The + /// TargetInstrInfo::AnalyzeBranch method can be used to get more information + /// about this branch. + bool isUnconditionalBranch() const { + return isBranch() & isBarrier() & !isIndirectBranch(); + } + + // isPredicable - Return true if this instruction has a predicate operand that + // controls execution. It may be set to 'always', or may be set to other + /// values. There are various methods in TargetInstrInfo that can be used to + /// control and modify the predicate in this instruction. + bool isPredicable() const { + return Flags & (1 << MCID::Predicable); + } + + /// isCompare - Return true if this instruction is a comparison. + bool isCompare() const { + return Flags & (1 << MCID::Compare); + } + + /// isMoveImmediate - Return true if this instruction is a move immediate + /// (including conditional moves) instruction. + bool isMoveImmediate() const { + return Flags & (1 << MCID::MoveImm); + } + + /// isBitcast - Return true if this instruction is a bitcast instruction. + /// + bool isBitcast() const { + return Flags & (1 << MCID::Bitcast); + } + + /// isNotDuplicable - Return true if this instruction cannot be safely + /// duplicated. For example, if the instruction has a unique labels attached + /// to it, duplicating it would cause multiple definition errors. + bool isNotDuplicable() const { + return Flags & (1 << MCID::NotDuplicable); + } + + /// hasDelaySlot - Returns true if the specified instruction has a delay slot + /// which must be filled by the code generator. + bool hasDelaySlot() const { + return Flags & (1 << MCID::DelaySlot); + } + + /// canFoldAsLoad - Return true for instructions that can be folded as + /// memory operands in other instructions. The most common use for this + /// is instructions that are simple loads from memory that don't modify + /// the loaded value in any way, but it can also be used for instructions + /// that can be expressed as constant-pool loads, such as V_SETALLONES + /// on x86, to allow them to be folded when it is beneficial. + /// This should only be set on instructions that return a value in their + /// only virtual register definition. + bool canFoldAsLoad() const { + return Flags & (1 << MCID::FoldableAsLoad); + } + + //===--------------------------------------------------------------------===// + // Side Effect Analysis + //===--------------------------------------------------------------------===// + + /// mayLoad - Return true if this instruction could possibly read memory. + /// Instructions with this flag set are not necessarily simple load + /// instructions, they may load a value and modify it, for example. + bool mayLoad() const { + return Flags & (1 << MCID::MayLoad); + } + + + /// mayStore - Return true if this instruction could possibly modify memory. + /// Instructions with this flag set are not necessarily simple store + /// instructions, they may store a modified value based on their operands, or + /// may not actually modify anything, for example. + bool mayStore() const { + return Flags & (1 << MCID::MayStore); + } + + /// hasUnmodeledSideEffects - Return true if this instruction has side + /// effects that are not modeled by other flags. This does not return true + /// for instructions whose effects are captured by: + /// + /// 1. Their operand list and implicit definition/use list. Register use/def + /// info is explicit for instructions. + /// 2. Memory accesses. Use mayLoad/mayStore. + /// 3. Calling, branching, returning: use isCall/isReturn/isBranch. + /// + /// Examples of side effects would be modifying 'invisible' machine state like + /// a control register, flushing a cache, modifying a register invisible to + /// LLVM, etc. + /// + bool hasUnmodeledSideEffects() const { + return Flags & (1 << MCID::UnmodeledSideEffects); + } + + //===--------------------------------------------------------------------===// + // Flags that indicate whether an instruction can be modified by a method. + //===--------------------------------------------------------------------===// + + /// isCommutable - Return true if this may be a 2- or 3-address + /// instruction (of the form "X = op Y, Z, ..."), which produces the same + /// result if Y and Z are exchanged. If this flag is set, then the + /// TargetInstrInfo::commuteInstruction method may be used to hack on the + /// instruction. + /// + /// Note that this flag may be set on instructions that are only commutable + /// sometimes. In these cases, the call to commuteInstruction will fail. + /// Also note that some instructions require non-trivial modification to + /// commute them. + bool isCommutable() const { + return Flags & (1 << MCID::Commutable); + } + + /// isConvertibleTo3Addr - Return true if this is a 2-address instruction + /// which can be changed into a 3-address instruction if needed. Doing this + /// transformation can be profitable in the register allocator, because it + /// means that the instruction can use a 2-address form if possible, but + /// degrade into a less efficient form if the source and dest register cannot + /// be assigned to the same register. For example, this allows the x86 + /// backend to turn a "shl reg, 3" instruction into an LEA instruction, which + /// is the same speed as the shift but has bigger code size. + /// + /// If this returns true, then the target must implement the + /// TargetInstrInfo::convertToThreeAddress method for this instruction, which + /// is allowed to fail if the transformation isn't valid for this specific + /// instruction (e.g. shl reg, 4 on x86). + /// + bool isConvertibleTo3Addr() const { + return Flags & (1 << MCID::ConvertibleTo3Addr); + } + + /// usesCustomInsertionHook - Return true if this instruction requires + /// custom insertion support when the DAG scheduler is inserting it into a + /// machine basic block. If this is true for the instruction, it basically + /// means that it is a pseudo instruction used at SelectionDAG time that is + /// expanded out into magic code by the target when MachineInstrs are formed. + /// + /// If this is true, the TargetLoweringInfo::InsertAtEndOfBasicBlock method + /// is used to insert this into the MachineBasicBlock. + bool usesCustomInsertionHook() const { + return Flags & (1 << MCID::UsesCustomInserter); + } + + /// isRematerializable - Returns true if this instruction is a candidate for + /// remat. This flag is deprecated, please don't use it anymore. If this + /// flag is set, the isReallyTriviallyReMaterializable() method is called to + /// verify the instruction is really rematable. + bool isRematerializable() const { + return Flags & (1 << MCID::Rematerializable); + } + + /// isAsCheapAsAMove - Returns true if this instruction has the same cost (or + /// less) than a move instruction. This is useful during certain types of + /// optimizations (e.g., remat during two-address conversion or machine licm) + /// where we would like to remat or hoist the instruction, but not if it costs + /// more than moving the instruction into the appropriate register. Note, we + /// are not marking copies from and to the same register class with this flag. + bool isAsCheapAsAMove() const { + return Flags & (1 << MCID::CheapAsAMove); + } + + /// hasExtraSrcRegAllocReq - Returns true if this instruction source operands + /// have special register allocation requirements that are not captured by the + /// operand register classes. e.g. ARM::STRD's two source registers must be an + /// even / odd pair, ARM::STM registers have to be in ascending order. + /// Post-register allocation passes should not attempt to change allocations + /// for sources of instructions with this flag. + bool hasExtraSrcRegAllocReq() const { + return Flags & (1 << MCID::ExtraSrcRegAllocReq); + } + + /// hasExtraDefRegAllocReq - Returns true if this instruction def operands + /// have special register allocation requirements that are not captured by the + /// operand register classes. e.g. ARM::LDRD's two def registers must be an + /// even / odd pair, ARM::LDM registers have to be in ascending order. + /// Post-register allocation passes should not attempt to change allocations + /// for definitions of instructions with this flag. + bool hasExtraDefRegAllocReq() const { + return Flags & (1 << MCID::ExtraDefRegAllocReq); + } +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/MC/MCInstrInfo.h b/include/llvm/MC/MCInstrInfo.h new file mode 100644 index 0000000..9b15825 --- /dev/null +++ b/include/llvm/MC/MCInstrInfo.h @@ -0,0 +1,51 @@ +//===-- llvm/MC/MCInstrInfo.h - Target Instruction Info ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes the target machine instruction set. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCINSTRINFO_H +#define LLVM_MC_MCINSTRINFO_H + +#include "llvm/MC/MCInstrDesc.h" +#include + +namespace llvm { + +//--------------------------------------------------------------------------- +/// +/// MCInstrInfo - Interface to description of machine instruction set +/// +class MCInstrInfo { + const MCInstrDesc *Desc; // Raw array to allow static init'n + unsigned NumOpcodes; // Number of entries in the desc array + +public: + /// InitMCInstrInfo - Initialize MCInstrInfo, called by TableGen + /// auto-generated routines. *DO NOT USE*. + void InitMCInstrInfo(const MCInstrDesc *D, unsigned NO) { + Desc = D; + NumOpcodes = NO; + } + + unsigned getNumOpcodes() const { return NumOpcodes; } + + /// get - Return the machine instruction descriptor that corresponds to the + /// specified instruction opcode. + /// + const MCInstrDesc &get(unsigned Opcode) const { + assert(Opcode < NumOpcodes && "Invalid opcode!"); + return Desc[Opcode]; + } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/MC/MCRegisterInfo.h b/include/llvm/MC/MCRegisterInfo.h index 7b16e7b..caf98bb 100644 --- a/include/llvm/MC/MCRegisterInfo.h +++ b/include/llvm/MC/MCRegisterInfo.h @@ -52,7 +52,7 @@ struct MCRegisterDesc { class MCRegisterInfo { private: const MCRegisterDesc *Desc; // Pointer to the descriptor array - unsigned NumRegs; // Number of entries in the array + unsigned NumRegs; // Number of entries in the array public: /// InitMCRegisterInfo - Initialize MCRegisterInfo, called by TableGen diff --git a/include/llvm/Target/TargetInstrDesc.h b/include/llvm/Target/TargetInstrDesc.h deleted file mode 100644 index 6a540ab..0000000 --- a/include/llvm/Target/TargetInstrDesc.h +++ /dev/null @@ -1,493 +0,0 @@ -//===-- llvm/Target/TargetInstrDesc.h - Instruction Descriptors -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the TargetOperandInfo and TargetInstrDesc classes, which -// are used to describe target instructions and their operands. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TARGET_TARGETINSTRDESC_H -#define LLVM_TARGET_TARGETINSTRDESC_H - -#include "llvm/Support/DataTypes.h" - -namespace llvm { - -class TargetRegisterClass; -class TargetRegisterInfo; - -//===----------------------------------------------------------------------===// -// Machine Operand Flags and Description -//===----------------------------------------------------------------------===// - -namespace TOI { - // Operand constraints - enum OperandConstraint { - TIED_TO = 0, // Must be allocated the same register as. - EARLY_CLOBBER // Operand is an early clobber register operand - }; - - /// OperandFlags - These are flags set on operands, but should be considered - /// private, all access should go through the TargetOperandInfo accessors. - /// See the accessors for a description of what these are. - enum OperandFlags { - LookupPtrRegClass = 0, - Predicate, - OptionalDef - }; -} - -/// TargetOperandInfo - This holds information about one operand of a machine -/// instruction, indicating the register class for register operands, etc. -/// -class TargetOperandInfo { -public: - /// RegClass - This specifies the register class enumeration of the operand - /// if the operand is a register. If isLookupPtrRegClass is set, then this is - /// an index that is passed to TargetRegisterInfo::getPointerRegClass(x) to - /// get a dynamic register class. - short RegClass; - - /// Flags - These are flags from the TOI::OperandFlags enum. - unsigned short Flags; - - /// Lower 16 bits are used to specify which constraints are set. The higher 16 - /// bits are used to specify the value of constraints (4 bits each). - unsigned Constraints; - /// Currently no other information. - - /// isLookupPtrRegClass - Set if this operand is a pointer value and it - /// requires a callback to look up its register class. - bool isLookupPtrRegClass() const { return Flags&(1 <> Pos) & 0xf; - } - return -1; - } - - /// getOpcode - Return the opcode number for this descriptor. - unsigned getOpcode() const { - return Opcode; - } - - /// getName - Return the name of the record in the .td file for this - /// instruction, for example "ADD8ri". - const char *getName() const { - return Name; - } - - /// getNumOperands - Return the number of declared MachineOperands for this - /// MachineInstruction. Note that variadic (isVariadic() returns true) - /// instructions may have additional operands at the end of the list, and note - /// that the machine instruction may include implicit register def/uses as - /// well. - unsigned getNumOperands() const { - return NumOperands; - } - - /// getNumDefs - Return the number of MachineOperands that are register - /// definitions. Register definitions always occur at the start of the - /// machine operand list. This is the number of "outs" in the .td file, - /// and does not include implicit defs. - unsigned getNumDefs() const { - return NumDefs; - } - - /// isVariadic - Return true if this instruction can have a variable number of - /// operands. In this case, the variable operands will be after the normal - /// operands but before the implicit definitions and uses (if any are - /// present). - bool isVariadic() const { - return Flags & (1 << TID::Variadic); - } - - /// hasOptionalDef - Set if this instruction has an optional definition, e.g. - /// ARM instructions which can set condition code if 's' bit is set. - bool hasOptionalDef() const { - return Flags & (1 << TID::HasOptionalDef); - } - - /// getImplicitUses - Return a list of registers that are potentially - /// read by any instance of this machine instruction. For example, on X86, - /// the "adc" instruction adds two register operands and adds the carry bit in - /// from the flags register. In this case, the instruction is marked as - /// implicitly reading the flags. Likewise, the variable shift instruction on - /// X86 is marked as implicitly reading the 'CL' register, which it always - /// does. - /// - /// This method returns null if the instruction has no implicit uses. - const unsigned *getImplicitUses() const { - return ImplicitUses; - } - - /// getNumImplicitUses - Return the number of implicit uses this instruction - /// has. - unsigned getNumImplicitUses() const { - if (ImplicitUses == 0) return 0; - unsigned i = 0; - for (; ImplicitUses[i]; ++i) /*empty*/; - return i; - } - - - /// getImplicitDefs - Return a list of registers that are potentially - /// written by any instance of this machine instruction. For example, on X86, - /// many instructions implicitly set the flags register. In this case, they - /// are marked as setting the FLAGS. Likewise, many instructions always - /// deposit their result in a physical register. For example, the X86 divide - /// instruction always deposits the quotient and remainder in the EAX/EDX - /// registers. For that instruction, this will return a list containing the - /// EAX/EDX/EFLAGS registers. - /// - /// This method returns null if the instruction has no implicit defs. - const unsigned *getImplicitDefs() const { - return ImplicitDefs; - } - - /// getNumImplicitDefs - Return the number of implicit defs this instruction - /// has. - unsigned getNumImplicitDefs() const { - if (ImplicitDefs == 0) return 0; - unsigned i = 0; - for (; ImplicitDefs[i]; ++i) /*empty*/; - return i; - } - - /// hasImplicitUseOfPhysReg - Return true if this instruction implicitly - /// uses the specified physical register. - bool hasImplicitUseOfPhysReg(unsigned Reg) const { - if (const unsigned *ImpUses = ImplicitUses) - for (; *ImpUses; ++ImpUses) - if (*ImpUses == Reg) return true; - return false; - } - - /// hasImplicitDefOfPhysReg - Return true if this instruction implicitly - /// defines the specified physical register. - bool hasImplicitDefOfPhysReg(unsigned Reg) const { - if (const unsigned *ImpDefs = ImplicitDefs) - for (; *ImpDefs; ++ImpDefs) - if (*ImpDefs == Reg) return true; - return false; - } - - /// getSchedClass - Return the scheduling class for this instruction. The - /// scheduling class is an index into the InstrItineraryData table. This - /// returns zero if there is no known scheduling information for the - /// instruction. - /// - unsigned getSchedClass() const { - return SchedClass; - } - - bool isReturn() const { - return Flags & (1 << TID::Return); - } - - bool isCall() const { - return Flags & (1 << TID::Call); - } - - /// isBarrier - Returns true if the specified instruction stops control flow - /// from executing the instruction immediately following it. Examples include - /// unconditional branches and return instructions. - bool isBarrier() const { - return Flags & (1 << TID::Barrier); - } - - /// isTerminator - Returns true if this instruction part of the terminator for - /// a basic block. Typically this is things like return and branch - /// instructions. - /// - /// Various passes use this to insert code into the bottom of a basic block, - /// but before control flow occurs. - bool isTerminator() const { - return Flags & (1 << TID::Terminator); - } - - /// isBranch - Returns true if this is a conditional, unconditional, or - /// indirect branch. Predicates below can be used to discriminate between - /// these cases, and the TargetInstrInfo::AnalyzeBranch method can be used to - /// get more information. - bool isBranch() const { - return Flags & (1 << TID::Branch); - } - - /// isIndirectBranch - Return true if this is an indirect branch, such as a - /// branch through a register. - bool isIndirectBranch() const { - return Flags & (1 << TID::IndirectBranch); - } - - /// isConditionalBranch - Return true if this is a branch which may fall - /// through to the next instruction or may transfer control flow to some other - /// block. The TargetInstrInfo::AnalyzeBranch method can be used to get more - /// information about this branch. - bool isConditionalBranch() const { - return isBranch() & !isBarrier() & !isIndirectBranch(); - } - - /// isUnconditionalBranch - Return true if this is a branch which always - /// transfers control flow to some other block. The - /// TargetInstrInfo::AnalyzeBranch method can be used to get more information - /// about this branch. - bool isUnconditionalBranch() const { - return isBranch() & isBarrier() & !isIndirectBranch(); - } - - // isPredicable - Return true if this instruction has a predicate operand that - // controls execution. It may be set to 'always', or may be set to other - /// values. There are various methods in TargetInstrInfo that can be used to - /// control and modify the predicate in this instruction. - bool isPredicable() const { - return Flags & (1 << TID::Predicable); - } - - /// isCompare - Return true if this instruction is a comparison. - bool isCompare() const { - return Flags & (1 << TID::Compare); - } - - /// isMoveImmediate - Return true if this instruction is a move immediate - /// (including conditional moves) instruction. - bool isMoveImmediate() const { - return Flags & (1 << TID::MoveImm); - } - - /// isBitcast - Return true if this instruction is a bitcast instruction. - /// - bool isBitcast() const { - return Flags & (1 << TID::Bitcast); - } - - /// isNotDuplicable - Return true if this instruction cannot be safely - /// duplicated. For example, if the instruction has a unique labels attached - /// to it, duplicating it would cause multiple definition errors. - bool isNotDuplicable() const { - return Flags & (1 << TID::NotDuplicable); - } - - /// hasDelaySlot - Returns true if the specified instruction has a delay slot - /// which must be filled by the code generator. - bool hasDelaySlot() const { - return Flags & (1 << TID::DelaySlot); - } - - /// canFoldAsLoad - Return true for instructions that can be folded as - /// memory operands in other instructions. The most common use for this - /// is instructions that are simple loads from memory that don't modify - /// the loaded value in any way, but it can also be used for instructions - /// that can be expressed as constant-pool loads, such as V_SETALLONES - /// on x86, to allow them to be folded when it is beneficial. - /// This should only be set on instructions that return a value in their - /// only virtual register definition. - bool canFoldAsLoad() const { - return Flags & (1 << TID::FoldableAsLoad); - } - - //===--------------------------------------------------------------------===// - // Side Effect Analysis - //===--------------------------------------------------------------------===// - - /// mayLoad - Return true if this instruction could possibly read memory. - /// Instructions with this flag set are not necessarily simple load - /// instructions, they may load a value and modify it, for example. - bool mayLoad() const { - return Flags & (1 << TID::MayLoad); - } - - - /// mayStore - Return true if this instruction could possibly modify memory. - /// Instructions with this flag set are not necessarily simple store - /// instructions, they may store a modified value based on their operands, or - /// may not actually modify anything, for example. - bool mayStore() const { - return Flags & (1 << TID::MayStore); - } - - /// hasUnmodeledSideEffects - Return true if this instruction has side - /// effects that are not modeled by other flags. This does not return true - /// for instructions whose effects are captured by: - /// - /// 1. Their operand list and implicit definition/use list. Register use/def - /// info is explicit for instructions. - /// 2. Memory accesses. Use mayLoad/mayStore. - /// 3. Calling, branching, returning: use isCall/isReturn/isBranch. - /// - /// Examples of side effects would be modifying 'invisible' machine state like - /// a control register, flushing a cache, modifying a register invisible to - /// LLVM, etc. - /// - bool hasUnmodeledSideEffects() const { - return Flags & (1 << TID::UnmodeledSideEffects); - } - - //===--------------------------------------------------------------------===// - // Flags that indicate whether an instruction can be modified by a method. - //===--------------------------------------------------------------------===// - - /// isCommutable - Return true if this may be a 2- or 3-address - /// instruction (of the form "X = op Y, Z, ..."), which produces the same - /// result if Y and Z are exchanged. If this flag is set, then the - /// TargetInstrInfo::commuteInstruction method may be used to hack on the - /// instruction. - /// - /// Note that this flag may be set on instructions that are only commutable - /// sometimes. In these cases, the call to commuteInstruction will fail. - /// Also note that some instructions require non-trivial modification to - /// commute them. - bool isCommutable() const { - return Flags & (1 << TID::Commutable); - } - - /// isConvertibleTo3Addr - Return true if this is a 2-address instruction - /// which can be changed into a 3-address instruction if needed. Doing this - /// transformation can be profitable in the register allocator, because it - /// means that the instruction can use a 2-address form if possible, but - /// degrade into a less efficient form if the source and dest register cannot - /// be assigned to the same register. For example, this allows the x86 - /// backend to turn a "shl reg, 3" instruction into an LEA instruction, which - /// is the same speed as the shift but has bigger code size. - /// - /// If this returns true, then the target must implement the - /// TargetInstrInfo::convertToThreeAddress method for this instruction, which - /// is allowed to fail if the transformation isn't valid for this specific - /// instruction (e.g. shl reg, 4 on x86). - /// - bool isConvertibleTo3Addr() const { - return Flags & (1 << TID::ConvertibleTo3Addr); - } - - /// usesCustomInsertionHook - Return true if this instruction requires - /// custom insertion support when the DAG scheduler is inserting it into a - /// machine basic block. If this is true for the instruction, it basically - /// means that it is a pseudo instruction used at SelectionDAG time that is - /// expanded out into magic code by the target when MachineInstrs are formed. - /// - /// If this is true, the TargetLoweringInfo::InsertAtEndOfBasicBlock method - /// is used to insert this into the MachineBasicBlock. - bool usesCustomInsertionHook() const { - return Flags & (1 << TID::UsesCustomInserter); - } - - /// isRematerializable - Returns true if this instruction is a candidate for - /// remat. This flag is deprecated, please don't use it anymore. If this - /// flag is set, the isReallyTriviallyReMaterializable() method is called to - /// verify the instruction is really rematable. - bool isRematerializable() const { - return Flags & (1 << TID::Rematerializable); - } - - /// isAsCheapAsAMove - Returns true if this instruction has the same cost (or - /// less) than a move instruction. This is useful during certain types of - /// optimizations (e.g., remat during two-address conversion or machine licm) - /// where we would like to remat or hoist the instruction, but not if it costs - /// more than moving the instruction into the appropriate register. Note, we - /// are not marking copies from and to the same register class with this flag. - bool isAsCheapAsAMove() const { - return Flags & (1 << TID::CheapAsAMove); - } - - /// hasExtraSrcRegAllocReq - Returns true if this instruction source operands - /// have special register allocation requirements that are not captured by the - /// operand register classes. e.g. ARM::STRD's two source registers must be an - /// even / odd pair, ARM::STM registers have to be in ascending order. - /// Post-register allocation passes should not attempt to change allocations - /// for sources of instructions with this flag. - bool hasExtraSrcRegAllocReq() const { - return Flags & (1 << TID::ExtraSrcRegAllocReq); - } - - /// hasExtraDefRegAllocReq - Returns true if this instruction def operands - /// have special register allocation requirements that are not captured by the - /// operand register classes. e.g. ARM::LDRD's two def registers must be an - /// even / odd pair, ARM::LDM registers have to be in ascending order. - /// Post-register allocation passes should not attempt to change allocations - /// for definitions of instructions with this flag. - bool hasExtraDefRegAllocReq() const { - return Flags & (1 << TID::ExtraDefRegAllocReq); - } -}; - -} // end namespace llvm - -#endif diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h index 8c00741..271f9e7 100644 --- a/include/llvm/Target/TargetInstrInfo.h +++ b/include/llvm/Target/TargetInstrInfo.h @@ -14,7 +14,7 @@ #ifndef LLVM_TARGET_TARGETINSTRINFO_H #define LLVM_TARGET_TARGETINSTRINFO_H -#include "llvm/Target/TargetInstrDesc.h" +#include "llvm/MC/MCInstrInfo.h" #include "llvm/CodeGen/MachineFunction.h" namespace llvm { @@ -40,29 +40,16 @@ template class SmallVectorImpl; /// /// TargetInstrInfo - Interface to description of machine instruction set /// -class TargetInstrInfo { - const TargetInstrDesc *Descriptors; // Raw array to allow static init'n - unsigned NumOpcodes; // Number of entries in the desc array - +class TargetInstrInfo : public MCInstrInfo { TargetInstrInfo(const TargetInstrInfo &); // DO NOT IMPLEMENT void operator=(const TargetInstrInfo &); // DO NOT IMPLEMENT public: - TargetInstrInfo(const TargetInstrDesc *desc, unsigned NumOpcodes); + TargetInstrInfo(const MCInstrDesc *desc, unsigned NumOpcodes); virtual ~TargetInstrInfo(); - unsigned getNumOpcodes() const { return NumOpcodes; } - - /// get - Return the machine instruction descriptor that corresponds to the - /// specified instruction opcode. - /// - const TargetInstrDesc &get(unsigned Opcode) const { - assert(Opcode < NumOpcodes && "Invalid opcode!"); - return Descriptors[Opcode]; - } - /// getRegClass - Givem a machine instruction descriptor, returns the register /// class constraint for OpNum, or NULL. - const TargetRegisterClass *getRegClass(const TargetInstrDesc &TID, + const TargetRegisterClass *getRegClass(const MCInstrDesc &TID, unsigned OpNum, const TargetRegisterInfo *TRI) const; @@ -677,7 +664,7 @@ public: /// libcodegen, not in libtarget. class TargetInstrInfoImpl : public TargetInstrInfo { protected: - TargetInstrInfoImpl(const TargetInstrDesc *desc, unsigned NumOpcodes) + TargetInstrInfoImpl(const MCInstrDesc *desc, unsigned NumOpcodes) : TargetInstrInfo(desc, NumOpcodes) {} public: virtual void ReplaceTailWithBranchTo(MachineBasicBlock::iterator OldInst, diff --git a/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h index 94cfd8b..1ca7651 100644 --- a/include/llvm/Target/TargetRegisterInfo.h +++ b/include/llvm/Target/TargetRegisterInfo.h @@ -495,7 +495,7 @@ public: } /// getRegClass - Returns the register class associated with the enumeration - /// value. See class TargetOperandInfo. + /// value. See class MCOperandInfo. const TargetRegisterClass *getRegClass(unsigned i) const { assert(i < getNumRegClasses() && "Register Class ID out of range"); return RegClassBegin[i]; diff --git a/lib/CodeGen/BranchFolding.cpp b/lib/CodeGen/BranchFolding.cpp index d95f77e..4df7b46 100644 --- a/lib/CodeGen/BranchFolding.cpp +++ b/lib/CodeGen/BranchFolding.cpp @@ -421,10 +421,10 @@ static unsigned EstimateRuntime(MachineBasicBlock::iterator I, for (; I != E; ++I) { if (I->isDebugValue()) continue; - const TargetInstrDesc &TID = I->getDesc(); - if (TID.isCall()) + const MCInstrDesc &MCID = I->getDesc(); + if (MCID.isCall()) Time += 10; - else if (TID.mayLoad() || TID.mayStore()) + else if (MCID.mayLoad() || MCID.mayStore()) Time += 2; else ++Time; diff --git a/lib/CodeGen/ExpandISelPseudos.cpp b/lib/CodeGen/ExpandISelPseudos.cpp index ebc2fc9..a67140e 100644 --- a/lib/CodeGen/ExpandISelPseudos.cpp +++ b/lib/CodeGen/ExpandISelPseudos.cpp @@ -62,8 +62,8 @@ bool ExpandISelPseudos::runOnMachineFunction(MachineFunction &MF) { MachineInstr *MI = MBBI++; // If MI is a pseudo, expand it. - const TargetInstrDesc &TID = MI->getDesc(); - if (TID.usesCustomInsertionHook()) { + const MCInstrDesc &MCID = MI->getDesc(); + if (MCID.usesCustomInsertionHook()) { Changed = true; MachineBasicBlock *NewMBB = TLI->EmitInstrWithCustomInserter(MI, MBB); diff --git a/lib/CodeGen/IfConversion.cpp b/lib/CodeGen/IfConversion.cpp index 8b2c981..d8355ab 100644 --- a/lib/CodeGen/IfConversion.cpp +++ b/lib/CodeGen/IfConversion.cpp @@ -651,12 +651,12 @@ void IfConverter::ScanInstructions(BBInfo &BBI) { if (I->isDebugValue()) continue; - const TargetInstrDesc &TID = I->getDesc(); - if (TID.isNotDuplicable()) + const MCInstrDesc &MCID = I->getDesc(); + if (MCID.isNotDuplicable()) BBI.CannotBeCopied = true; bool isPredicated = TII->isPredicated(I); - bool isCondBr = BBI.IsBrAnalyzable && TID.isConditionalBranch(); + bool isCondBr = BBI.IsBrAnalyzable && MCID.isConditionalBranch(); if (!isCondBr) { if (!isPredicated) { @@ -1414,9 +1414,9 @@ void IfConverter::CopyAndPredicateBlock(BBInfo &ToBBI, BBInfo &FromBBI, for (MachineBasicBlock::iterator I = FromBBI.BB->begin(), E = FromBBI.BB->end(); I != E; ++I) { - const TargetInstrDesc &TID = I->getDesc(); + const MCInstrDesc &MCID = I->getDesc(); // Do not copy the end of the block branches. - if (IgnoreBr && TID.isBranch()) + if (IgnoreBr && MCID.isBranch()) break; MachineInstr *MI = MF.CloneMachineInstr(I); diff --git a/lib/CodeGen/MachineBasicBlock.cpp b/lib/CodeGen/MachineBasicBlock.cpp index c0f71d2..8f0fb46 100644 --- a/lib/CodeGen/MachineBasicBlock.cpp +++ b/lib/CodeGen/MachineBasicBlock.cpp @@ -22,7 +22,6 @@ #include "llvm/MC/MCContext.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetData.h" -#include "llvm/Target/TargetInstrDesc.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Assembly/Writer.h" diff --git a/lib/CodeGen/MachineCSE.cpp b/lib/CodeGen/MachineCSE.cpp index f97ccf6..3a60a37 100644 --- a/lib/CodeGen/MachineCSE.cpp +++ b/lib/CodeGen/MachineCSE.cpp @@ -260,12 +260,12 @@ bool MachineCSE::isCSECandidate(MachineInstr *MI) { return false; // Ignore stuff that we obviously can't move. - const TargetInstrDesc &TID = MI->getDesc(); - if (TID.mayStore() || TID.isCall() || TID.isTerminator() || + const MCInstrDesc &MCID = MI->getDesc(); + if (MCID.mayStore() || MCID.isCall() || MCID.isTerminator() || MI->hasUnmodeledSideEffects()) return false; - if (TID.mayLoad()) { + if (MCID.mayLoad()) { // Okay, this instruction does a load. As a refinement, we allow the target // to decide whether the loaded value is actually a constant. If so, we can // actually use it as a load. diff --git a/lib/CodeGen/MachineFunction.cpp b/lib/CodeGen/MachineFunction.cpp index 50750a5..cd25156 100644 --- a/lib/CodeGen/MachineFunction.cpp +++ b/lib/CodeGen/MachineFunction.cpp @@ -152,10 +152,10 @@ void MachineFunction::RenumberBlocks(MachineBasicBlock *MBB) { /// of `new MachineInstr'. /// MachineInstr * -MachineFunction::CreateMachineInstr(const TargetInstrDesc &TID, +MachineFunction::CreateMachineInstr(const MCInstrDesc &MCID, DebugLoc DL, bool NoImp) { return new (InstructionRecycler.Allocate(Allocator)) - MachineInstr(TID, DL, NoImp); + MachineInstr(MCID, DL, NoImp); } /// CloneMachineInstr - Create a new MachineInstr which is a copy of the diff --git a/lib/CodeGen/MachineInstr.cpp b/lib/CodeGen/MachineInstr.cpp index 938b83d..0995106 100644 --- a/lib/CodeGen/MachineInstr.cpp +++ b/lib/CodeGen/MachineInstr.cpp @@ -24,10 +24,10 @@ #include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/MC/MCInstrDesc.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetInstrInfo.h" -#include "llvm/Target/TargetInstrDesc.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/DebugInfo.h" @@ -457,9 +457,9 @@ raw_ostream &llvm::operator<<(raw_ostream &OS, const MachineMemOperand &MMO) { //===----------------------------------------------------------------------===// /// MachineInstr ctor - This constructor creates a dummy MachineInstr with -/// TID NULL and no operands. +/// MCID NULL and no operands. MachineInstr::MachineInstr() - : TID(0), NumImplicitOps(0), Flags(0), AsmPrinterFlags(0), + : MCID(0), NumImplicitOps(0), Flags(0), AsmPrinterFlags(0), MemRefs(0), MemRefsEnd(0), Parent(0) { // Make sure that we get added to a machine basicblock @@ -467,23 +467,23 @@ MachineInstr::MachineInstr() } void MachineInstr::addImplicitDefUseOperands() { - if (TID->ImplicitDefs) - for (const unsigned *ImpDefs = TID->ImplicitDefs; *ImpDefs; ++ImpDefs) + if (MCID->ImplicitDefs) + for (const unsigned *ImpDefs = MCID->ImplicitDefs; *ImpDefs; ++ImpDefs) addOperand(MachineOperand::CreateReg(*ImpDefs, true, true)); - if (TID->ImplicitUses) - for (const unsigned *ImpUses = TID->ImplicitUses; *ImpUses; ++ImpUses) + if (MCID->ImplicitUses) + for (const unsigned *ImpUses = MCID->ImplicitUses; *ImpUses; ++ImpUses) addOperand(MachineOperand::CreateReg(*ImpUses, false, true)); } /// MachineInstr ctor - This constructor creates a MachineInstr and adds the /// implicit operands. It reserves space for the number of operands specified by -/// the TargetInstrDesc. -MachineInstr::MachineInstr(const TargetInstrDesc &tid, bool NoImp) - : TID(&tid), NumImplicitOps(0), Flags(0), AsmPrinterFlags(0), +/// the MCInstrDesc. +MachineInstr::MachineInstr(const MCInstrDesc &tid, bool NoImp) + : MCID(&tid), NumImplicitOps(0), Flags(0), AsmPrinterFlags(0), MemRefs(0), MemRefsEnd(0), Parent(0) { if (!NoImp) - NumImplicitOps = TID->getNumImplicitDefs() + TID->getNumImplicitUses(); - Operands.reserve(NumImplicitOps + TID->getNumOperands()); + NumImplicitOps = MCID->getNumImplicitDefs() + MCID->getNumImplicitUses(); + Operands.reserve(NumImplicitOps + MCID->getNumOperands()); if (!NoImp) addImplicitDefUseOperands(); // Make sure that we get added to a machine basicblock @@ -491,13 +491,13 @@ MachineInstr::MachineInstr(const TargetInstrDesc &tid, bool NoImp) } /// MachineInstr ctor - As above, but with a DebugLoc. -MachineInstr::MachineInstr(const TargetInstrDesc &tid, const DebugLoc dl, +MachineInstr::MachineInstr(const MCInstrDesc &tid, const DebugLoc dl, bool NoImp) - : TID(&tid), NumImplicitOps(0), Flags(0), AsmPrinterFlags(0), + : MCID(&tid), NumImplicitOps(0), Flags(0), AsmPrinterFlags(0), MemRefs(0), MemRefsEnd(0), Parent(0), debugLoc(dl) { if (!NoImp) - NumImplicitOps = TID->getNumImplicitDefs() + TID->getNumImplicitUses(); - Operands.reserve(NumImplicitOps + TID->getNumOperands()); + NumImplicitOps = MCID->getNumImplicitDefs() + MCID->getNumImplicitUses(); + Operands.reserve(NumImplicitOps + MCID->getNumOperands()); if (!NoImp) addImplicitDefUseOperands(); // Make sure that we get added to a machine basicblock @@ -507,12 +507,12 @@ MachineInstr::MachineInstr(const TargetInstrDesc &tid, const DebugLoc dl, /// MachineInstr ctor - Work exactly the same as the ctor two above, except /// that the MachineInstr is created and added to the end of the specified /// basic block. -MachineInstr::MachineInstr(MachineBasicBlock *MBB, const TargetInstrDesc &tid) - : TID(&tid), NumImplicitOps(0), Flags(0), AsmPrinterFlags(0), +MachineInstr::MachineInstr(MachineBasicBlock *MBB, const MCInstrDesc &tid) + : MCID(&tid), NumImplicitOps(0), Flags(0), AsmPrinterFlags(0), MemRefs(0), MemRefsEnd(0), Parent(0) { assert(MBB && "Cannot use inserting ctor with null basic block!"); - NumImplicitOps = TID->getNumImplicitDefs() + TID->getNumImplicitUses(); - Operands.reserve(NumImplicitOps + TID->getNumOperands()); + NumImplicitOps = MCID->getNumImplicitDefs() + MCID->getNumImplicitUses(); + Operands.reserve(NumImplicitOps + MCID->getNumOperands()); addImplicitDefUseOperands(); // Make sure that we get added to a machine basicblock LeakDetector::addGarbageObject(this); @@ -522,12 +522,12 @@ MachineInstr::MachineInstr(MachineBasicBlock *MBB, const TargetInstrDesc &tid) /// MachineInstr ctor - As above, but with a DebugLoc. /// MachineInstr::MachineInstr(MachineBasicBlock *MBB, const DebugLoc dl, - const TargetInstrDesc &tid) - : TID(&tid), NumImplicitOps(0), Flags(0), AsmPrinterFlags(0), + const MCInstrDesc &tid) + : MCID(&tid), NumImplicitOps(0), Flags(0), AsmPrinterFlags(0), MemRefs(0), MemRefsEnd(0), Parent(0), debugLoc(dl) { assert(MBB && "Cannot use inserting ctor with null basic block!"); - NumImplicitOps = TID->getNumImplicitDefs() + TID->getNumImplicitUses(); - Operands.reserve(NumImplicitOps + TID->getNumOperands()); + NumImplicitOps = MCID->getNumImplicitDefs() + MCID->getNumImplicitUses(); + Operands.reserve(NumImplicitOps + MCID->getNumOperands()); addImplicitDefUseOperands(); // Make sure that we get added to a machine basicblock LeakDetector::addGarbageObject(this); @@ -537,7 +537,7 @@ MachineInstr::MachineInstr(MachineBasicBlock *MBB, const DebugLoc dl, /// MachineInstr ctor - Copies MachineInstr arg exactly /// MachineInstr::MachineInstr(MachineFunction &MF, const MachineInstr &MI) - : TID(&MI.getDesc()), NumImplicitOps(0), Flags(0), AsmPrinterFlags(0), + : MCID(&MI.getDesc()), NumImplicitOps(0), Flags(0), AsmPrinterFlags(0), MemRefs(MI.MemRefs), MemRefsEnd(MI.MemRefsEnd), Parent(0), debugLoc(MI.getDebugLoc()) { Operands.reserve(MI.getNumOperands()); @@ -624,7 +624,7 @@ void MachineInstr::addOperand(const MachineOperand &Op) { Operands.back().AddRegOperandToRegInfo(RegInfo); // If the register operand is flagged as early, mark the operand as such unsigned OpNo = Operands.size() - 1; - if (TID->getOperandConstraint(OpNo, TOI::EARLY_CLOBBER) != -1) + if (MCID->getOperandConstraint(OpNo, MCOI::EARLY_CLOBBER) != -1) Operands[OpNo].setIsEarlyClobber(true); } return; @@ -646,7 +646,7 @@ void MachineInstr::addOperand(const MachineOperand &Op) { if (Operands[OpNo].isReg()) { Operands[OpNo].AddRegOperandToRegInfo(0); // If the register operand is flagged as early, mark the operand as such - if (TID->getOperandConstraint(OpNo, TOI::EARLY_CLOBBER) != -1) + if (MCID->getOperandConstraint(OpNo, MCOI::EARLY_CLOBBER) != -1) Operands[OpNo].setIsEarlyClobber(true); } @@ -671,7 +671,7 @@ void MachineInstr::addOperand(const MachineOperand &Op) { if (Operands[OpNo].isReg()) { Operands[OpNo].AddRegOperandToRegInfo(RegInfo); // If the register operand is flagged as early, mark the operand as such - if (TID->getOperandConstraint(OpNo, TOI::EARLY_CLOBBER) != -1) + if (MCID->getOperandConstraint(OpNo, MCOI::EARLY_CLOBBER) != -1) Operands[OpNo].setIsEarlyClobber(true); } @@ -694,7 +694,7 @@ void MachineInstr::addOperand(const MachineOperand &Op) { // If the register operand is flagged as early, mark the operand as such if (Operands[OpNo].isReg() - && TID->getOperandConstraint(OpNo, TOI::EARLY_CLOBBER) != -1) + && MCID->getOperandConstraint(OpNo, MCOI::EARLY_CLOBBER) != -1) Operands[OpNo].setIsEarlyClobber(true); } } @@ -820,8 +820,8 @@ void MachineInstr::eraseFromParent() { /// OperandComplete - Return true if it's illegal to add a new operand /// bool MachineInstr::OperandsComplete() const { - unsigned short NumOperands = TID->getNumOperands(); - if (!TID->isVariadic() && getNumOperands()-NumImplicitOps >= NumOperands) + unsigned short NumOperands = MCID->getNumOperands(); + if (!MCID->isVariadic() && getNumOperands()-NumImplicitOps >= NumOperands) return true; // Broken: we have all the operands of this instruction! return false; } @@ -829,8 +829,8 @@ bool MachineInstr::OperandsComplete() const { /// getNumExplicitOperands - Returns the number of non-implicit operands. /// unsigned MachineInstr::getNumExplicitOperands() const { - unsigned NumOperands = TID->getNumOperands(); - if (!TID->isVariadic()) + unsigned NumOperands = MCID->getNumOperands(); + if (!MCID->isVariadic()) return NumOperands; for (unsigned i = NumOperands, e = getNumOperands(); i != e; ++i) { @@ -931,10 +931,10 @@ MachineInstr::findRegisterDefOperandIdx(unsigned Reg, bool isDead, bool Overlap, /// operand list that is used to represent the predicate. It returns -1 if /// none is found. int MachineInstr::findFirstPredOperandIdx() const { - const TargetInstrDesc &TID = getDesc(); - if (TID.isPredicable()) { + const MCInstrDesc &MCID = getDesc(); + if (MCID.isPredicable()) { for (unsigned i = 0, e = getNumOperands(); i != e; ++i) - if (TID.OpInfo[i].isPredicate()) + if (MCID.OpInfo[i].isPredicate()) return i; } @@ -990,11 +990,11 @@ isRegTiedToUseOperand(unsigned DefOpIdx, unsigned *UseOpIdx) const { } assert(getOperand(DefOpIdx).isDef() && "DefOpIdx is not a def!"); - const TargetInstrDesc &TID = getDesc(); - for (unsigned i = 0, e = TID.getNumOperands(); i != e; ++i) { + const MCInstrDesc &MCID = getDesc(); + for (unsigned i = 0, e = MCID.getNumOperands(); i != e; ++i) { const MachineOperand &MO = getOperand(i); if (MO.isReg() && MO.isUse() && - TID.getOperandConstraint(i, TOI::TIED_TO) == (int)DefOpIdx) { + MCID.getOperandConstraint(i, MCOI::TIED_TO) == (int)DefOpIdx) { if (UseOpIdx) *UseOpIdx = (unsigned)i; return true; @@ -1050,13 +1050,13 @@ isRegTiedToDefOperand(unsigned UseOpIdx, unsigned *DefOpIdx) const { return false; } - const TargetInstrDesc &TID = getDesc(); - if (UseOpIdx >= TID.getNumOperands()) + const MCInstrDesc &MCID = getDesc(); + if (UseOpIdx >= MCID.getNumOperands()) return false; const MachineOperand &MO = getOperand(UseOpIdx); if (!MO.isReg() || !MO.isUse()) return false; - int DefIdx = TID.getOperandConstraint(UseOpIdx, TOI::TIED_TO); + int DefIdx = MCID.getOperandConstraint(UseOpIdx, MCOI::TIED_TO); if (DefIdx == -1) return false; if (DefOpIdx) @@ -1096,11 +1096,11 @@ void MachineInstr::copyKillDeadInfo(const MachineInstr *MI) { /// copyPredicates - Copies predicate operand(s) from MI. void MachineInstr::copyPredicates(const MachineInstr *MI) { - const TargetInstrDesc &TID = MI->getDesc(); - if (!TID.isPredicable()) + const MCInstrDesc &MCID = MI->getDesc(); + if (!MCID.isPredicable()) return; for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { - if (TID.OpInfo[i].isPredicate()) { + if (MCID.OpInfo[i].isPredicate()) { // Predicated operands must be last operands. addOperand(MI->getOperand(i)); } @@ -1137,13 +1137,13 @@ bool MachineInstr::isSafeToMove(const TargetInstrInfo *TII, AliasAnalysis *AA, bool &SawStore) const { // Ignore stuff that we obviously can't move. - if (TID->mayStore() || TID->isCall()) { + if (MCID->mayStore() || MCID->isCall()) { SawStore = true; return false; } if (isLabel() || isDebugValue() || - TID->isTerminator() || hasUnmodeledSideEffects()) + MCID->isTerminator() || hasUnmodeledSideEffects()) return false; // See if this instruction does a load. If so, we have to guarantee that the @@ -1151,7 +1151,7 @@ bool MachineInstr::isSafeToMove(const TargetInstrInfo *TII, // destination. The check for isInvariantLoad gives the targe the chance to // classify the load as always returning a constant, e.g. a constant pool // load. - if (TID->mayLoad() && !isInvariantLoad(AA)) + if (MCID->mayLoad() && !isInvariantLoad(AA)) // Otherwise, this is a real load. If there is a store between the load and // end of block, or if the load is volatile, we can't move it. return !SawStore && !hasVolatileMemoryRef(); @@ -1191,9 +1191,9 @@ bool MachineInstr::isSafeToReMat(const TargetInstrInfo *TII, /// have no volatile memory references. bool MachineInstr::hasVolatileMemoryRef() const { // An instruction known never to access memory won't have a volatile access. - if (!TID->mayStore() && - !TID->mayLoad() && - !TID->isCall() && + if (!MCID->mayStore() && + !MCID->mayLoad() && + !MCID->isCall() && !hasUnmodeledSideEffects()) return false; @@ -1217,7 +1217,7 @@ bool MachineInstr::hasVolatileMemoryRef() const { /// *all* loads the instruction does are invariant (if it does multiple loads). bool MachineInstr::isInvariantLoad(AliasAnalysis *AA) const { // If the instruction doesn't load at all, it isn't an invariant load. - if (!TID->mayLoad()) + if (!MCID->mayLoad()) return false; // If the instruction has lost its memoperands, conservatively assume that @@ -1421,10 +1421,10 @@ void MachineInstr::print(raw_ostream &OS, const TargetMachine *TM) const { if (FirstOp) FirstOp = false; else OS << ","; OS << " "; if (i < getDesc().NumOperands) { - const TargetOperandInfo &TOI = getDesc().OpInfo[i]; - if (TOI.isPredicate()) + const MCOperandInfo &MCOI = getDesc().OpInfo[i]; + if (MCOI.isPredicate()) OS << "pred:"; - if (TOI.isOptionalDef()) + if (MCOI.isOptionalDef()) OS << "opt:"; } if (isDebugValue() && MO.isMetadata()) { diff --git a/lib/CodeGen/MachineLICM.cpp b/lib/CodeGen/MachineLICM.cpp index cfd0325..28a81e1 100644 --- a/lib/CodeGen/MachineLICM.cpp +++ b/lib/CodeGen/MachineLICM.cpp @@ -1018,9 +1018,9 @@ MachineInstr *MachineLICM::ExtractHoistableLoad(MachineInstr *MI) { /*UnfoldStore=*/false, &LoadRegIndex); if (NewOpc == 0) return 0; - const TargetInstrDesc &TID = TII->get(NewOpc); - if (TID.getNumDefs() != 1) return 0; - const TargetRegisterClass *RC = TII->getRegClass(TID, LoadRegIndex, TRI); + const MCInstrDesc &MID = TII->get(NewOpc); + if (MID.getNumDefs() != 1) return 0; + const TargetRegisterClass *RC = TII->getRegClass(MID, LoadRegIndex, TRI); // Ok, we're unfolding. Create a temporary register and do the unfold. unsigned Reg = MRI->createVirtualRegister(RC); diff --git a/lib/CodeGen/MachineVerifier.cpp b/lib/CodeGen/MachineVerifier.cpp index d3f8b02..7a55852 100644 --- a/lib/CodeGen/MachineVerifier.cpp +++ b/lib/CodeGen/MachineVerifier.cpp @@ -541,19 +541,19 @@ MachineVerifier::visitMachineBasicBlockBefore(const MachineBasicBlock *MBB) { } void MachineVerifier::visitMachineInstrBefore(const MachineInstr *MI) { - const TargetInstrDesc &TI = MI->getDesc(); - if (MI->getNumOperands() < TI.getNumOperands()) { + const MCInstrDesc &MCID = MI->getDesc(); + if (MI->getNumOperands() < MCID.getNumOperands()) { report("Too few operands", MI); - *OS << TI.getNumOperands() << " operands expected, but " + *OS << MCID.getNumOperands() << " operands expected, but " << MI->getNumExplicitOperands() << " given.\n"; } // Check the MachineMemOperands for basic consistency. for (MachineInstr::mmo_iterator I = MI->memoperands_begin(), E = MI->memoperands_end(); I != E; ++I) { - if ((*I)->isLoad() && !TI.mayLoad()) + if ((*I)->isLoad() && !MCID.mayLoad()) report("Missing mayLoad flag", MI); - if ((*I)->isStore() && !TI.mayStore()) + if ((*I)->isStore() && !MCID.mayStore()) report("Missing mayStore flag", MI); } @@ -575,29 +575,30 @@ void MachineVerifier::visitMachineInstrBefore(const MachineInstr *MI) { void MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) { const MachineInstr *MI = MO->getParent(); - const TargetInstrDesc &TI = MI->getDesc(); - const TargetOperandInfo &TOI = TI.OpInfo[MONum]; + const MCInstrDesc &MCID = MI->getDesc(); + const MCOperandInfo &MCOI = MCID.OpInfo[MONum]; - // The first TI.NumDefs operands must be explicit register defines - if (MONum < TI.getNumDefs()) { + // The first MCID.NumDefs operands must be explicit register defines + if (MONum < MCID.getNumDefs()) { if (!MO->isReg()) report("Explicit definition must be a register", MO, MONum); else if (!MO->isDef()) report("Explicit definition marked as use", MO, MONum); else if (MO->isImplicit()) report("Explicit definition marked as implicit", MO, MONum); - } else if (MONum < TI.getNumOperands()) { + } else if (MONum < MCID.getNumOperands()) { // Don't check if it's the last operand in a variadic instruction. See, // e.g., LDM_RET in the arm back end. - if (MO->isReg() && !(TI.isVariadic() && MONum == TI.getNumOperands()-1)) { - if (MO->isDef() && !TOI.isOptionalDef()) + if (MO->isReg() && + !(MCID.isVariadic() && MONum == MCID.getNumOperands()-1)) { + if (MO->isDef() && !MCOI.isOptionalDef()) report("Explicit operand marked as def", MO, MONum); if (MO->isImplicit()) report("Explicit operand marked as implicit", MO, MONum); } } else { // ARM adds %reg0 operands to indicate predicates. We'll allow that. - if (MO->isReg() && !MO->isImplicit() && !TI.isVariadic() && MO->getReg()) + if (MO->isReg() && !MO->isImplicit() && !MCID.isVariadic() && MO->getReg()) report("Extra explicit operand on non-variadic instruction", MO, MONum); } @@ -709,7 +710,7 @@ MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) { } // Check register classes. - if (MONum < TI.getNumOperands() && !MO->isImplicit()) { + if (MONum < MCID.getNumOperands() && !MO->isImplicit()) { unsigned SubIdx = MO->getSubReg(); if (TargetRegisterInfo::isPhysicalRegister(Reg)) { @@ -723,7 +724,7 @@ MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) { } sr = s; } - if (const TargetRegisterClass *DRC = TII->getRegClass(TI, MONum, TRI)) { + if (const TargetRegisterClass *DRC = TII->getRegClass(MCID,MONum,TRI)) { if (!DRC->contains(sr)) { report("Illegal physical register for instruction", MO, MONum); *OS << TRI->getName(sr) << " is not a " @@ -743,7 +744,7 @@ MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) { } RC = SRC; } - if (const TargetRegisterClass *DRC = TII->getRegClass(TI, MONum, TRI)) { + if (const TargetRegisterClass *DRC = TII->getRegClass(MCID,MONum,TRI)) { if (!RC->hasSuperClassEq(DRC)) { report("Illegal virtual register for instruction", MO, MONum); *OS << "Expected a " << DRC->getName() << " register, but got a " @@ -765,11 +766,11 @@ MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) { LiveInts && !LiveInts->isNotInMIMap(MI)) { LiveInterval &LI = LiveStks->getInterval(MO->getIndex()); SlotIndex Idx = LiveInts->getInstructionIndex(MI); - if (TI.mayLoad() && !LI.liveAt(Idx.getUseIndex())) { + if (MCID.mayLoad() && !LI.liveAt(Idx.getUseIndex())) { report("Instruction loads from dead spill slot", MO, MONum); *OS << "Live stack: " << LI << '\n'; } - if (TI.mayStore() && !LI.liveAt(Idx.getDefIndex())) { + if (MCID.mayStore() && !LI.liveAt(Idx.getDefIndex())) { report("Instruction stores to dead spill slot", MO, MONum); *OS << "Live stack: " << LI << '\n'; } diff --git a/lib/CodeGen/PeepholeOptimizer.cpp b/lib/CodeGen/PeepholeOptimizer.cpp index c105bb0..c523e39 100644 --- a/lib/CodeGen/PeepholeOptimizer.cpp +++ b/lib/CodeGen/PeepholeOptimizer.cpp @@ -353,10 +353,10 @@ bool PeepholeOptimizer::OptimizeCmpInstr(MachineInstr *MI, bool PeepholeOptimizer::isMoveImmediate(MachineInstr *MI, SmallSet &ImmDefRegs, DenseMap &ImmDefMIs) { - const TargetInstrDesc &TID = MI->getDesc(); - if (!TID.isMoveImmediate()) + const MCInstrDesc &MCID = MI->getDesc(); + if (!MCID.isMoveImmediate()) return false; - if (TID.getNumDefs() != 1) + if (MCID.getNumDefs() != 1) return false; unsigned Reg = MI->getOperand(0).getReg(); if (TargetRegisterInfo::isVirtualRegister(Reg)) { @@ -429,16 +429,16 @@ bool PeepholeOptimizer::runOnMachineFunction(MachineFunction &MF) { continue; } - const TargetInstrDesc &TID = MI->getDesc(); + const MCInstrDesc &MCID = MI->getDesc(); - if (TID.isBitcast()) { + if (MCID.isBitcast()) { if (OptimizeBitcastInstr(MI, MBB)) { // MI is deleted. Changed = true; MII = First ? I->begin() : llvm::next(PMII); continue; } - } else if (TID.isCompare()) { + } else if (MCID.isCompare()) { if (OptimizeCmpInstr(MI, MBB)) { // MI is deleted. Changed = true; diff --git a/lib/CodeGen/RegAllocFast.cpp b/lib/CodeGen/RegAllocFast.cpp index 15b0111..ee23194 100644 --- a/lib/CodeGen/RegAllocFast.cpp +++ b/lib/CodeGen/RegAllocFast.cpp @@ -118,7 +118,7 @@ namespace { // SkippedInstrs - Descriptors of instructions whose clobber list was // ignored because all registers were spilled. It is still necessary to // mark all the clobbered registers as used by the function. - SmallPtrSet SkippedInstrs; + SmallPtrSet SkippedInstrs; // isBulkSpilling - This flag is set when LiveRegMap will be cleared // completely after spilling all live registers. LiveRegMap entries should @@ -777,7 +777,7 @@ void RAFast::AllocateBasicBlock() { // Otherwise, sequentially allocate each instruction in the MBB. while (MII != MBB->end()) { MachineInstr *MI = MII++; - const TargetInstrDesc &TID = MI->getDesc(); + const MCInstrDesc &MCID = MI->getDesc(); DEBUG({ dbgs() << "\n>> " << *MI << "Regs:"; for (unsigned Reg = 1, E = TRI->getNumRegs(); Reg != E; ++Reg) { @@ -890,7 +890,7 @@ void RAFast::AllocateBasicBlock() { VirtOpEnd = i+1; if (MO.isUse()) { hasTiedOps = hasTiedOps || - TID.getOperandConstraint(i, TOI::TIED_TO) != -1; + MCID.getOperandConstraint(i, MCOI::TIED_TO) != -1; } else { if (MO.isEarlyClobber()) hasEarlyClobbers = true; @@ -920,7 +920,7 @@ void RAFast::AllocateBasicBlock() { // We didn't detect inline asm tied operands above, so just make this extra // pass for all inline asm. if (MI->isInlineAsm() || hasEarlyClobbers || hasPartialRedefs || - (hasTiedOps && (hasPhysDefs || TID.getNumDefs() > 1))) { + (hasTiedOps && (hasPhysDefs || MCID.getNumDefs() > 1))) { handleThroughOperands(MI, VirtDead); // Don't attempt coalescing when we have funny stuff going on. CopyDst = 0; @@ -965,7 +965,7 @@ void RAFast::AllocateBasicBlock() { } unsigned DefOpEnd = MI->getNumOperands(); - if (TID.isCall()) { + if (MCID.isCall()) { // Spill all virtregs before a call. This serves two purposes: 1. If an // exception is thrown, the landing pad is going to expect to find // registers in their spill slots, and 2. we don't have to wade through @@ -976,7 +976,7 @@ void RAFast::AllocateBasicBlock() { // The imp-defs are skipped below, but we still need to mark those // registers as used by the function. - SkippedInstrs.insert(&TID); + SkippedInstrs.insert(&MCID); } // Third scan. @@ -1062,7 +1062,7 @@ bool RAFast::runOnMachineFunction(MachineFunction &Fn) { MRI->closePhysRegsUsed(*TRI); // Add the clobber lists for all the instructions we skipped earlier. - for (SmallPtrSet::const_iterator + for (SmallPtrSet::const_iterator I = SkippedInstrs.begin(), E = SkippedInstrs.end(); I != E; ++I) if (const unsigned *Defs = (*I)->getImplicitDefs()) while (*Defs) diff --git a/lib/CodeGen/RegisterCoalescer.cpp b/lib/CodeGen/RegisterCoalescer.cpp index d59843f..8826df4 100644 --- a/lib/CodeGen/RegisterCoalescer.cpp +++ b/lib/CodeGen/RegisterCoalescer.cpp @@ -526,8 +526,8 @@ bool RegisterCoalescer::RemoveCopyByCommutingDef(const CoalescerPair &CP, MachineInstr *DefMI = li_->getInstructionFromIndex(AValNo->def); if (!DefMI) return false; - const TargetInstrDesc &TID = DefMI->getDesc(); - if (!TID.isCommutable()) + const MCInstrDesc &MCID = DefMI->getDesc(); + if (!MCID.isCommutable()) return false; // If DefMI is a two-address instruction then commuting it will change the // destination register. @@ -687,21 +687,21 @@ bool RegisterCoalescer::ReMaterializeTrivialDef(LiveInterval &SrcInt, if (!DefMI) return false; assert(DefMI && "Defining instruction disappeared"); - const TargetInstrDesc &TID = DefMI->getDesc(); - if (!TID.isAsCheapAsAMove()) + const MCInstrDesc &MCID = DefMI->getDesc(); + if (!MCID.isAsCheapAsAMove()) return false; if (!tii_->isTriviallyReMaterializable(DefMI, AA)) return false; bool SawStore = false; if (!DefMI->isSafeToMove(tii_, AA, SawStore)) return false; - if (TID.getNumDefs() != 1) + if (MCID.getNumDefs() != 1) return false; if (!DefMI->isImplicitDef()) { // Make sure the copy destination register class fits the instruction // definition register class. The mismatch can happen as a result of earlier // extract_subreg, insert_subreg, subreg_to_reg coalescing. - const TargetRegisterClass *RC = tii_->getRegClass(TID, 0, tri_); + const TargetRegisterClass *RC = tii_->getRegClass(MCID, 0, tri_); if (TargetRegisterInfo::isVirtualRegister(DstReg)) { if (mri_->getRegClass(DstReg) != RC) return false; @@ -712,13 +712,13 @@ bool RegisterCoalescer::ReMaterializeTrivialDef(LiveInterval &SrcInt, // If destination register has a sub-register index on it, make sure it // matches the instruction register class. if (DstSubIdx) { - const TargetInstrDesc &TID = DefMI->getDesc(); - if (TID.getNumDefs() != 1) + const MCInstrDesc &MCID = DefMI->getDesc(); + if (MCID.getNumDefs() != 1) return false; const TargetRegisterClass *DstRC = mri_->getRegClass(DstReg); const TargetRegisterClass *DstSubRC = DstRC->getSubRegisterRegClass(DstSubIdx); - const TargetRegisterClass *DefRC = tii_->getRegClass(TID, 0, tri_); + const TargetRegisterClass *DefRC = tii_->getRegClass(MCID, 0, tri_); if (DefRC == DstRC) DstSubIdx = 0; else if (DefRC != DstSubRC) diff --git a/lib/CodeGen/ScheduleDAG.cpp b/lib/CodeGen/ScheduleDAG.cpp index f328493..21375b2 100644 --- a/lib/CodeGen/ScheduleDAG.cpp +++ b/lib/CodeGen/ScheduleDAG.cpp @@ -45,7 +45,7 @@ ScheduleDAG::ScheduleDAG(MachineFunction &mf) ScheduleDAG::~ScheduleDAG() {} /// getInstrDesc helper to handle SDNodes. -const TargetInstrDesc *ScheduleDAG::getNodeDesc(const SDNode *Node) const { +const MCInstrDesc *ScheduleDAG::getNodeDesc(const SDNode *Node) const { if (!Node || !Node->isMachineOpcode()) return NULL; return &TII->get(Node->getMachineOpcode()); } diff --git a/lib/CodeGen/ScheduleDAGInstrs.cpp b/lib/CodeGen/ScheduleDAGInstrs.cpp index 2363df4..94941ec 100644 --- a/lib/CodeGen/ScheduleDAGInstrs.cpp +++ b/lib/CodeGen/ScheduleDAGInstrs.cpp @@ -236,13 +236,13 @@ void ScheduleDAGInstrs::BuildSchedGraph(AliasAnalysis *AA) { continue; } - const TargetInstrDesc &TID = MI->getDesc(); - assert(!TID.isTerminator() && !MI->isLabel() && + const MCInstrDesc &MCID = MI->getDesc(); + assert(!MCID.isTerminator() && !MI->isLabel() && "Cannot schedule terminators or labels!"); // Create the SUnit for this MI. SUnit *SU = NewSUnit(MI); - SU->isCall = TID.isCall(); - SU->isCommutable = TID.isCommutable(); + SU->isCall = MCID.isCall(); + SU->isCommutable = MCID.isCommutable(); // Assign the Latency field of SU using target-provided information. if (UnitLatencies) @@ -309,13 +309,13 @@ void ScheduleDAGInstrs::BuildSchedGraph(AliasAnalysis *AA) { if (SpecialAddressLatency != 0 && !UnitLatencies && UseSU != &ExitSU) { MachineInstr *UseMI = UseSU->getInstr(); - const TargetInstrDesc &UseTID = UseMI->getDesc(); + const MCInstrDesc &UseMCID = UseMI->getDesc(); int RegUseIndex = UseMI->findRegisterUseOperandIdx(Reg); assert(RegUseIndex >= 0 && "UseMI doesn's use register!"); if (RegUseIndex >= 0 && - (UseTID.mayLoad() || UseTID.mayStore()) && - (unsigned)RegUseIndex < UseTID.getNumOperands() && - UseTID.OpInfo[RegUseIndex].isLookupPtrRegClass()) + (UseMCID.mayLoad() || UseMCID.mayStore()) && + (unsigned)RegUseIndex < UseMCID.getNumOperands() && + UseMCID.OpInfo[RegUseIndex].isLookupPtrRegClass()) LDataLatency += SpecialAddressLatency; } // Adjust the dependence latency using operand def/use @@ -352,17 +352,17 @@ void ScheduleDAGInstrs::BuildSchedGraph(AliasAnalysis *AA) { unsigned Count = I->second.second; const MachineInstr *UseMI = UseMO->getParent(); unsigned UseMOIdx = UseMO - &UseMI->getOperand(0); - const TargetInstrDesc &UseTID = UseMI->getDesc(); + const MCInstrDesc &UseMCID = UseMI->getDesc(); // TODO: If we knew the total depth of the region here, we could // handle the case where the whole loop is inside the region but // is large enough that the isScheduleHigh trick isn't needed. - if (UseMOIdx < UseTID.getNumOperands()) { + if (UseMOIdx < UseMCID.getNumOperands()) { // Currently, we only support scheduling regions consisting of // single basic blocks. Check to see if the instruction is in // the same region by checking to see if it has the same parent. if (UseMI->getParent() != MI->getParent()) { unsigned Latency = SU->Latency; - if (UseTID.OpInfo[UseMOIdx].isLookupPtrRegClass()) + if (UseMCID.OpInfo[UseMOIdx].isLookupPtrRegClass()) Latency += SpecialAddressLatency; // This is a wild guess as to the portion of the latency which // will be overlapped by work done outside the current @@ -374,7 +374,7 @@ void ScheduleDAGInstrs::BuildSchedGraph(AliasAnalysis *AA) { /*isMustAlias=*/false, /*isArtificial=*/true)); } else if (SpecialAddressLatency > 0 && - UseTID.OpInfo[UseMOIdx].isLookupPtrRegClass()) { + UseMCID.OpInfo[UseMOIdx].isLookupPtrRegClass()) { // The entire loop body is within the current scheduling region // and the latency of this operation is assumed to be greater // than the latency of the loop. @@ -417,9 +417,9 @@ void ScheduleDAGInstrs::BuildSchedGraph(AliasAnalysis *AA) { // produce more precise dependence information. #define STORE_LOAD_LATENCY 1 unsigned TrueMemOrderLatency = 0; - if (TID.isCall() || MI->hasUnmodeledSideEffects() || + if (MCID.isCall() || MI->hasUnmodeledSideEffects() || (MI->hasVolatileMemoryRef() && - (!TID.mayLoad() || !MI->isInvariantLoad(AA)))) { + (!MCID.mayLoad() || !MI->isInvariantLoad(AA)))) { // Be conservative with these and add dependencies on all memory // references, even those that are known to not alias. for (std::map::iterator I = @@ -458,7 +458,7 @@ void ScheduleDAGInstrs::BuildSchedGraph(AliasAnalysis *AA) { PendingLoads.clear(); AliasMemDefs.clear(); AliasMemUses.clear(); - } else if (TID.mayStore()) { + } else if (MCID.mayStore()) { bool MayAlias = true; TrueMemOrderLatency = STORE_LOAD_LATENCY; if (const Value *V = getUnderlyingObjectForInstr(MI, MFI, MayAlias)) { @@ -514,7 +514,7 @@ void ScheduleDAGInstrs::BuildSchedGraph(AliasAnalysis *AA) { /*Reg=*/0, /*isNormalMemory=*/false, /*isMustAlias=*/false, /*isArtificial=*/true)); - } else if (TID.mayLoad()) { + } else if (MCID.mayLoad()) { bool MayAlias = true; TrueMemOrderLatency = 0; if (MI->isInvariantLoad(AA)) { diff --git a/lib/CodeGen/ScoreboardHazardRecognizer.cpp b/lib/CodeGen/ScoreboardHazardRecognizer.cpp index e6d7ded..35e48cd 100644 --- a/lib/CodeGen/ScoreboardHazardRecognizer.cpp +++ b/lib/CodeGen/ScoreboardHazardRecognizer.cpp @@ -115,12 +115,12 @@ ScoreboardHazardRecognizer::getHazardType(SUnit *SU, int Stalls) { // Use the itinerary for the underlying instruction to check for // free FU's in the scoreboard at the appropriate future cycles. - const TargetInstrDesc *TID = DAG->getInstrDesc(SU); - if (TID == NULL) { + const MCInstrDesc *MCID = DAG->getInstrDesc(SU); + if (MCID == NULL) { // Don't check hazards for non-machineinstr Nodes. return NoHazard; } - unsigned idx = TID->getSchedClass(); + unsigned idx = MCID->getSchedClass(); for (const InstrStage *IS = ItinData->beginStage(idx), *E = ItinData->endStage(idx); IS != E; ++IS) { // We must find one of the stage's units free for every cycle the @@ -173,16 +173,16 @@ void ScoreboardHazardRecognizer::EmitInstruction(SUnit *SU) { // Use the itinerary for the underlying instruction to reserve FU's // in the scoreboard at the appropriate future cycles. - const TargetInstrDesc *TID = DAG->getInstrDesc(SU); - assert(TID && "The scheduler must filter non-machineinstrs"); - if (DAG->TII->isZeroCost(TID->Opcode)) + const MCInstrDesc *MCID = DAG->getInstrDesc(SU); + assert(MCID && "The scheduler must filter non-machineinstrs"); + if (DAG->TII->isZeroCost(MCID->Opcode)) return; ++IssueCount; unsigned cycle = 0; - unsigned idx = TID->getSchedClass(); + unsigned idx = MCID->getSchedClass(); for (const InstrStage *IS = ItinData->beginStage(idx), *E = ItinData->endStage(idx); IS != E; ++IS) { // We must reserve one of the stage's units for every cycle the diff --git a/lib/CodeGen/SelectionDAG/FastISel.cpp b/lib/CodeGen/SelectionDAG/FastISel.cpp index a7d629e..580239a 100644 --- a/lib/CodeGen/SelectionDAG/FastISel.cpp +++ b/lib/CodeGen/SelectionDAG/FastISel.cpp @@ -569,7 +569,7 @@ bool FastISel::SelectCall(const User *I) { case Intrinsic::dbg_value: { // This form of DBG_VALUE is target-independent. const DbgValueInst *DI = cast(Call); - const TargetInstrDesc &II = TII.get(TargetOpcode::DBG_VALUE); + const MCInstrDesc &II = TII.get(TargetOpcode::DBG_VALUE); const Value *V = DI->getValue(); if (!V) { // Currently the optimizer can produce this; insert an undef to @@ -1112,7 +1112,7 @@ unsigned FastISel::createResultReg(const TargetRegisterClass* RC) { unsigned FastISel::FastEmitInst_(unsigned MachineInstOpcode, const TargetRegisterClass* RC) { unsigned ResultReg = createResultReg(RC); - const TargetInstrDesc &II = TII.get(MachineInstOpcode); + const MCInstrDesc &II = TII.get(MachineInstOpcode); BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg); return ResultReg; @@ -1122,7 +1122,7 @@ unsigned FastISel::FastEmitInst_r(unsigned MachineInstOpcode, const TargetRegisterClass *RC, unsigned Op0, bool Op0IsKill) { unsigned ResultReg = createResultReg(RC); - const TargetInstrDesc &II = TII.get(MachineInstOpcode); + const MCInstrDesc &II = TII.get(MachineInstOpcode); if (II.getNumDefs() >= 1) BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) @@ -1142,7 +1142,7 @@ unsigned FastISel::FastEmitInst_rr(unsigned MachineInstOpcode, unsigned Op0, bool Op0IsKill, unsigned Op1, bool Op1IsKill) { unsigned ResultReg = createResultReg(RC); - const TargetInstrDesc &II = TII.get(MachineInstOpcode); + const MCInstrDesc &II = TII.get(MachineInstOpcode); if (II.getNumDefs() >= 1) BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) @@ -1164,7 +1164,7 @@ unsigned FastISel::FastEmitInst_rrr(unsigned MachineInstOpcode, unsigned Op1, bool Op1IsKill, unsigned Op2, bool Op2IsKill) { unsigned ResultReg = createResultReg(RC); - const TargetInstrDesc &II = TII.get(MachineInstOpcode); + const MCInstrDesc &II = TII.get(MachineInstOpcode); if (II.getNumDefs() >= 1) BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) @@ -1187,7 +1187,7 @@ unsigned FastISel::FastEmitInst_ri(unsigned MachineInstOpcode, unsigned Op0, bool Op0IsKill, uint64_t Imm) { unsigned ResultReg = createResultReg(RC); - const TargetInstrDesc &II = TII.get(MachineInstOpcode); + const MCInstrDesc &II = TII.get(MachineInstOpcode); if (II.getNumDefs() >= 1) BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) @@ -1208,7 +1208,7 @@ unsigned FastISel::FastEmitInst_rii(unsigned MachineInstOpcode, unsigned Op0, bool Op0IsKill, uint64_t Imm1, uint64_t Imm2) { unsigned ResultReg = createResultReg(RC); - const TargetInstrDesc &II = TII.get(MachineInstOpcode); + const MCInstrDesc &II = TII.get(MachineInstOpcode); if (II.getNumDefs() >= 1) BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) @@ -1231,7 +1231,7 @@ unsigned FastISel::FastEmitInst_rf(unsigned MachineInstOpcode, unsigned Op0, bool Op0IsKill, const ConstantFP *FPImm) { unsigned ResultReg = createResultReg(RC); - const TargetInstrDesc &II = TII.get(MachineInstOpcode); + const MCInstrDesc &II = TII.get(MachineInstOpcode); if (II.getNumDefs() >= 1) BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) @@ -1253,7 +1253,7 @@ unsigned FastISel::FastEmitInst_rri(unsigned MachineInstOpcode, unsigned Op1, bool Op1IsKill, uint64_t Imm) { unsigned ResultReg = createResultReg(RC); - const TargetInstrDesc &II = TII.get(MachineInstOpcode); + const MCInstrDesc &II = TII.get(MachineInstOpcode); if (II.getNumDefs() >= 1) BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) @@ -1275,7 +1275,7 @@ unsigned FastISel::FastEmitInst_i(unsigned MachineInstOpcode, const TargetRegisterClass *RC, uint64_t Imm) { unsigned ResultReg = createResultReg(RC); - const TargetInstrDesc &II = TII.get(MachineInstOpcode); + const MCInstrDesc &II = TII.get(MachineInstOpcode); if (II.getNumDefs() >= 1) BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg).addImm(Imm); @@ -1291,7 +1291,7 @@ unsigned FastISel::FastEmitInst_ii(unsigned MachineInstOpcode, const TargetRegisterClass *RC, uint64_t Imm1, uint64_t Imm2) { unsigned ResultReg = createResultReg(RC); - const TargetInstrDesc &II = TII.get(MachineInstOpcode); + const MCInstrDesc &II = TII.get(MachineInstOpcode); if (II.getNumDefs() >= 1) BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) diff --git a/lib/CodeGen/SelectionDAG/InstrEmitter.cpp b/lib/CodeGen/SelectionDAG/InstrEmitter.cpp index 1759255..f0f4743 100644 --- a/lib/CodeGen/SelectionDAG/InstrEmitter.cpp +++ b/lib/CodeGen/SelectionDAG/InstrEmitter.cpp @@ -106,7 +106,7 @@ EmitCopyFromReg(SDNode *Node, unsigned ResNo, bool IsClone, bool IsCloned, continue; Match = false; if (User->isMachineOpcode()) { - const TargetInstrDesc &II = TII->get(User->getMachineOpcode()); + const MCInstrDesc &II = TII->get(User->getMachineOpcode()); const TargetRegisterClass *RC = 0; if (i+II.getNumDefs() < II.getNumOperands()) RC = TII->getRegClass(II, i+II.getNumDefs(), TRI); @@ -178,7 +178,7 @@ unsigned InstrEmitter::getDstOfOnlyCopyToRegUse(SDNode *Node, } void InstrEmitter::CreateVirtualRegisters(SDNode *Node, MachineInstr *MI, - const TargetInstrDesc &II, + const MCInstrDesc &II, bool IsClone, bool IsCloned, DenseMap &VRBaseMap) { assert(Node->getMachineOpcode() != TargetOpcode::IMPLICIT_DEF && @@ -242,7 +242,7 @@ unsigned InstrEmitter::getVR(SDValue Op, Op.getMachineOpcode() == TargetOpcode::IMPLICIT_DEF) { // Add an IMPLICIT_DEF instruction before every use. unsigned VReg = getDstOfOnlyCopyToRegUse(Op.getNode(), Op.getResNo()); - // IMPLICIT_DEF can produce any type of result so its TargetInstrDesc + // IMPLICIT_DEF can produce any type of result so its MCInstrDesc // does not include operand register class info. if (!VReg) { const TargetRegisterClass *RC = TLI->getRegClassFor(Op.getValueType()); @@ -265,7 +265,7 @@ unsigned InstrEmitter::getVR(SDValue Op, void InstrEmitter::AddRegisterOperand(MachineInstr *MI, SDValue Op, unsigned IIOpNum, - const TargetInstrDesc *II, + const MCInstrDesc *II, DenseMap &VRBaseMap, bool IsDebug, bool IsClone, bool IsCloned) { assert(Op.getValueType() != MVT::Other && @@ -275,9 +275,9 @@ InstrEmitter::AddRegisterOperand(MachineInstr *MI, SDValue Op, unsigned VReg = getVR(Op, VRBaseMap); assert(TargetRegisterInfo::isVirtualRegister(VReg) && "Not a vreg?"); - const TargetInstrDesc &TID = MI->getDesc(); - bool isOptDef = IIOpNum < TID.getNumOperands() && - TID.OpInfo[IIOpNum].isOptionalDef(); + const MCInstrDesc &MCID = MI->getDesc(); + bool isOptDef = IIOpNum < MCID.getNumOperands() && + MCID.OpInfo[IIOpNum].isOptionalDef(); // If the instruction requires a register in a different class, create // a new virtual register and copy the value into it. @@ -286,7 +286,7 @@ InstrEmitter::AddRegisterOperand(MachineInstr *MI, SDValue Op, const TargetRegisterClass *DstRC = 0; if (IIOpNum < II->getNumOperands()) DstRC = TII->getRegClass(*II, IIOpNum, TRI); - assert((DstRC || (TID.isVariadic() && IIOpNum >= TID.getNumOperands())) && + assert((DstRC || (MCID.isVariadic() && IIOpNum >= MCID.getNumOperands())) && "Don't have operand info for this instruction!"); if (DstRC && !SrcRC->hasSuperClassEq(DstRC)) { unsigned NewVReg = MRI->createVirtualRegister(DstRC); @@ -312,7 +312,7 @@ InstrEmitter::AddRegisterOperand(MachineInstr *MI, SDValue Op, while (Idx > 0 && MI->getOperand(Idx-1).isReg() && MI->getOperand(Idx-1).isImplicit()) --Idx; - bool isTied = MI->getDesc().getOperandConstraint(Idx, TOI::TIED_TO) != -1; + bool isTied = MI->getDesc().getOperandConstraint(Idx, MCOI::TIED_TO) != -1; if (isTied) isKill = false; } @@ -330,7 +330,7 @@ InstrEmitter::AddRegisterOperand(MachineInstr *MI, SDValue Op, /// assertions only. void InstrEmitter::AddOperand(MachineInstr *MI, SDValue Op, unsigned IIOpNum, - const TargetInstrDesc *II, + const MCInstrDesc *II, DenseMap &VRBaseMap, bool IsDebug, bool IsClone, bool IsCloned) { if (Op.isMachineOpcode()) { @@ -556,7 +556,7 @@ void InstrEmitter::EmitRegSequence(SDNode *Node, unsigned NumOps = Node->getNumOperands(); assert((NumOps & 1) == 1 && "REG_SEQUENCE must have an odd number of operands!"); - const TargetInstrDesc &II = TII->get(TargetOpcode::REG_SEQUENCE); + const MCInstrDesc &II = TII->get(TargetOpcode::REG_SEQUENCE); for (unsigned i = 1; i != NumOps; ++i) { SDValue Op = Node->getOperand(i); if ((i & 1) == 0) { @@ -597,7 +597,7 @@ InstrEmitter::EmitDbgValue(SDDbgValue *SD, return TII->emitFrameIndexDebugValue(*MF, FrameIx, Offset, MDPtr, DL); } // Otherwise, we're going to create an instruction here. - const TargetInstrDesc &II = TII->get(TargetOpcode::DBG_VALUE); + const MCInstrDesc &II = TII->get(TargetOpcode::DBG_VALUE); MachineInstrBuilder MIB = BuildMI(*MF, DL, II); if (SD->getKind() == SDDbgValue::SDNODE) { SDNode *Node = SD->getSDNode(); @@ -668,7 +668,7 @@ EmitMachineNode(SDNode *Node, bool IsClone, bool IsCloned, // We want a unique VR for each IMPLICIT_DEF use. return; - const TargetInstrDesc &II = TII->get(Opc); + const MCInstrDesc &II = TII->get(Opc); unsigned NumResults = CountResults(Node); unsigned NodeOperands = CountOperands(Node); bool HasPhysRegOuts = NumResults > II.getNumDefs() && II.getImplicitDefs()!=0; @@ -697,9 +697,9 @@ EmitMachineNode(SDNode *Node, bool IsClone, bool IsCloned, UsedRegs.push_back(cast(F->getOperand(1))->getReg()); else { // Collect declared implicit uses. - const TargetInstrDesc &TID = TII->get(F->getMachineOpcode()); - UsedRegs.append(TID.getImplicitUses(), - TID.getImplicitUses() + TID.getNumImplicitUses()); + const MCInstrDesc &MCID = TII->get(F->getMachineOpcode()); + UsedRegs.append(MCID.getImplicitUses(), + MCID.getImplicitUses() + MCID.getNumImplicitUses()); // In addition to declared implicit uses, we must also check for // direct RegisterSDNode operands. for (unsigned i = 0, e = F->getNumOperands(); i != e; ++i) diff --git a/lib/CodeGen/SelectionDAG/InstrEmitter.h b/lib/CodeGen/SelectionDAG/InstrEmitter.h index 02c044c..19fc044 100644 --- a/lib/CodeGen/SelectionDAG/InstrEmitter.h +++ b/lib/CodeGen/SelectionDAG/InstrEmitter.h @@ -22,7 +22,7 @@ namespace llvm { -class TargetInstrDesc; +class MCInstrDesc; class SDDbgValue; class InstrEmitter { @@ -49,7 +49,7 @@ class InstrEmitter { unsigned ResNo) const; void CreateVirtualRegisters(SDNode *Node, MachineInstr *MI, - const TargetInstrDesc &II, + const MCInstrDesc &II, bool IsClone, bool IsCloned, DenseMap &VRBaseMap); @@ -63,7 +63,7 @@ class InstrEmitter { /// not in the required register class. void AddRegisterOperand(MachineInstr *MI, SDValue Op, unsigned IIOpNum, - const TargetInstrDesc *II, + const MCInstrDesc *II, DenseMap &VRBaseMap, bool IsDebug, bool IsClone, bool IsCloned); @@ -73,7 +73,7 @@ class InstrEmitter { /// assertions only. void AddOperand(MachineInstr *MI, SDValue Op, unsigned IIOpNum, - const TargetInstrDesc *II, + const MCInstrDesc *II, DenseMap &VRBaseMap, bool IsDebug, bool IsClone, bool IsCloned); diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp index 6bed1db..b275c63 100644 --- a/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp +++ b/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp @@ -249,14 +249,14 @@ SUnit *ScheduleDAGFast::CopyAndMoveSuccessors(SUnit *SU) { assert(N->getNodeId() == -1 && "Node already inserted!"); N->setNodeId(NewSU->NodeNum); - const TargetInstrDesc &TID = TII->get(N->getMachineOpcode()); - for (unsigned i = 0; i != TID.getNumOperands(); ++i) { - if (TID.getOperandConstraint(i, TOI::TIED_TO) != -1) { + const MCInstrDesc &MCID = TII->get(N->getMachineOpcode()); + for (unsigned i = 0; i != MCID.getNumOperands(); ++i) { + if (MCID.getOperandConstraint(i, MCOI::TIED_TO) != -1) { NewSU->isTwoAddress = true; break; } } - if (TID.isCommutable()) + if (MCID.isCommutable()) NewSU->isCommutable = true; // LoadNode may already exist. This can happen when there is another @@ -422,10 +422,10 @@ void ScheduleDAGFast::InsertCopiesAndMoveSuccs(SUnit *SU, unsigned Reg, /// FIXME: Move to SelectionDAG? static EVT getPhysicalRegisterVT(SDNode *N, unsigned Reg, const TargetInstrInfo *TII) { - const TargetInstrDesc &TID = TII->get(N->getMachineOpcode()); - assert(TID.ImplicitDefs && "Physical reg def must be in implicit def list!"); - unsigned NumRes = TID.getNumDefs(); - for (const unsigned *ImpDef = TID.getImplicitDefs(); *ImpDef; ++ImpDef) { + const MCInstrDesc &MCID = TII->get(N->getMachineOpcode()); + assert(MCID.ImplicitDefs && "Physical reg def must be in implicit def list!"); + unsigned NumRes = MCID.getNumDefs(); + for (const unsigned *ImpDef = MCID.getImplicitDefs(); *ImpDef; ++ImpDef) { if (Reg == *ImpDef) break; ++NumRes; @@ -505,10 +505,10 @@ bool ScheduleDAGFast::DelayForLiveRegsBottomUp(SUnit *SU, } if (!Node->isMachineOpcode()) continue; - const TargetInstrDesc &TID = TII->get(Node->getMachineOpcode()); - if (!TID.ImplicitDefs) + const MCInstrDesc &MCID = TII->get(Node->getMachineOpcode()); + if (!MCID.ImplicitDefs) continue; - for (const unsigned *Reg = TID.ImplicitDefs; *Reg; ++Reg) { + for (const unsigned *Reg = MCID.ImplicitDefs; *Reg; ++Reg) { CheckForLiveRegDef(SU, *Reg, LiveRegDefs, RegAdded, LRegs, TRI); } } diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp index ff36e75..12b1838 100644 --- a/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp +++ b/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp @@ -302,7 +302,7 @@ static void GetCostForDef(const ScheduleDAGSDNodes::RegDefIter &RegDefPos, } unsigned Idx = RegDefPos.GetIdx(); - const TargetInstrDesc Desc = TII->get(Opcode); + const MCInstrDesc Desc = TII->get(Opcode); const TargetRegisterClass *RC = TII->getRegClass(Desc, Idx, TRI); RegClass = RC->getID(); // FIXME: Cost arbitrarily set to 1 because there doesn't seem to be a @@ -837,14 +837,14 @@ SUnit *ScheduleDAGRRList::CopyAndMoveSuccessors(SUnit *SU) { assert(N->getNodeId() == -1 && "Node already inserted!"); N->setNodeId(NewSU->NodeNum); - const TargetInstrDesc &TID = TII->get(N->getMachineOpcode()); - for (unsigned i = 0; i != TID.getNumOperands(); ++i) { - if (TID.getOperandConstraint(i, TOI::TIED_TO) != -1) { + const MCInstrDesc &MCID = TII->get(N->getMachineOpcode()); + for (unsigned i = 0; i != MCID.getNumOperands(); ++i) { + if (MCID.getOperandConstraint(i, MCOI::TIED_TO) != -1) { NewSU->isTwoAddress = true; break; } } - if (TID.isCommutable()) + if (MCID.isCommutable()) NewSU->isCommutable = true; InitNumRegDefsLeft(NewSU); @@ -1024,10 +1024,10 @@ void ScheduleDAGRRList::InsertCopiesAndMoveSuccs(SUnit *SU, unsigned Reg, /// FIXME: Move to SelectionDAG? static EVT getPhysicalRegisterVT(SDNode *N, unsigned Reg, const TargetInstrInfo *TII) { - const TargetInstrDesc &TID = TII->get(N->getMachineOpcode()); - assert(TID.ImplicitDefs && "Physical reg def must be in implicit def list!"); - unsigned NumRes = TID.getNumDefs(); - for (const unsigned *ImpDef = TID.getImplicitDefs(); *ImpDef; ++ImpDef) { + const MCInstrDesc &MCID = TII->get(N->getMachineOpcode()); + assert(MCID.ImplicitDefs && "Physical reg def must be in implicit def list!"); + unsigned NumRes = MCID.getNumDefs(); + for (const unsigned *ImpDef = MCID.getImplicitDefs(); *ImpDef; ++ImpDef) { if (Reg == *ImpDef) break; ++NumRes; @@ -1108,10 +1108,10 @@ DelayForLiveRegsBottomUp(SUnit *SU, SmallVector &LRegs) { if (!Node->isMachineOpcode()) continue; - const TargetInstrDesc &TID = TII->get(Node->getMachineOpcode()); - if (!TID.ImplicitDefs) + const MCInstrDesc &MCID = TII->get(Node->getMachineOpcode()); + if (!MCID.ImplicitDefs) continue; - for (const unsigned *Reg = TID.ImplicitDefs; *Reg; ++Reg) + for (const unsigned *Reg = MCID.ImplicitDefs; *Reg; ++Reg) CheckForLiveRegDef(SU, *Reg, LiveRegDefs, RegAdded, LRegs, TRI); } @@ -2606,11 +2606,11 @@ void RegReductionPQBase::initNodes(std::vector &sunits) { bool RegReductionPQBase::canClobber(const SUnit *SU, const SUnit *Op) { if (SU->isTwoAddress) { unsigned Opc = SU->getNode()->getMachineOpcode(); - const TargetInstrDesc &TID = TII->get(Opc); - unsigned NumRes = TID.getNumDefs(); - unsigned NumOps = TID.getNumOperands() - NumRes; + const MCInstrDesc &MCID = TII->get(Opc); + unsigned NumRes = MCID.getNumDefs(); + unsigned NumOps = MCID.getNumOperands() - NumRes; for (unsigned i = 0; i != NumOps; ++i) { - if (TID.getOperandConstraint(i+NumRes, TOI::TIED_TO) != -1) { + if (MCID.getOperandConstraint(i+NumRes, MCOI::TIED_TO) != -1) { SDNode *DU = SU->getNode()->getOperand(i).getNode(); if (DU->getNodeId() != -1 && Op->OrigNode == &(*SUnits)[DU->getNodeId()]) @@ -2790,11 +2790,11 @@ void RegReductionPQBase::AddPseudoTwoAddrDeps() { bool isLiveOut = hasOnlyLiveOutUses(SU); unsigned Opc = Node->getMachineOpcode(); - const TargetInstrDesc &TID = TII->get(Opc); - unsigned NumRes = TID.getNumDefs(); - unsigned NumOps = TID.getNumOperands() - NumRes; + const MCInstrDesc &MCID = TII->get(Opc); + unsigned NumRes = MCID.getNumDefs(); + unsigned NumOps = MCID.getNumOperands() - NumRes; for (unsigned j = 0; j != NumOps; ++j) { - if (TID.getOperandConstraint(j+NumRes, TOI::TIED_TO) == -1) + if (MCID.getOperandConstraint(j+NumRes, MCOI::TIED_TO) == -1) continue; SDNode *DU = SU->getNode()->getOperand(j).getNode(); if (DU->getNodeId() == -1) diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp index edd9e46..ca70ada 100644 --- a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp +++ b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp @@ -111,7 +111,7 @@ static void CheckForPhysRegDependency(SDNode *Def, SDNode *User, unsigned Op, unsigned ResNo = User->getOperand(2).getResNo(); if (Def->isMachineOpcode()) { - const TargetInstrDesc &II = TII->get(Def->getMachineOpcode()); + const MCInstrDesc &II = TII->get(Def->getMachineOpcode()); if (ResNo >= II.getNumDefs() && II.ImplicitDefs[ResNo - II.getNumDefs()] == Reg) { PhysReg = Reg; @@ -255,8 +255,8 @@ void ScheduleDAGSDNodes::ClusterNodes() { continue; unsigned Opc = Node->getMachineOpcode(); - const TargetInstrDesc &TID = TII->get(Opc); - if (TID.mayLoad()) + const MCInstrDesc &MCID = TII->get(Opc); + if (MCID.mayLoad()) // Cluster loads from "near" addresses into combined SUnits. ClusterNeighboringLoads(Node); } @@ -390,14 +390,14 @@ void ScheduleDAGSDNodes::AddSchedEdges() { if (MainNode->isMachineOpcode()) { unsigned Opc = MainNode->getMachineOpcode(); - const TargetInstrDesc &TID = TII->get(Opc); - for (unsigned i = 0; i != TID.getNumOperands(); ++i) { - if (TID.getOperandConstraint(i, TOI::TIED_TO) != -1) { + const MCInstrDesc &MCID = TII->get(Opc); + for (unsigned i = 0; i != MCID.getNumOperands(); ++i) { + if (MCID.getOperandConstraint(i, MCOI::TIED_TO) != -1) { SU->isTwoAddress = true; break; } } - if (TID.isCommutable()) + if (MCID.isCommutable()) SU->isCommutable = true; } diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 7a9439f..8cdc63d 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -354,9 +354,9 @@ bool SelectionDAGISel::runOnMachineFunction(MachineFunction &mf) { const MachineBasicBlock *MBB = I; for (MachineBasicBlock::const_iterator II = MBB->begin(), IE = MBB->end(); II != IE; ++II) { - const TargetInstrDesc &TID = TM.getInstrInfo()->get(II->getOpcode()); + const MCInstrDesc &MCID = TM.getInstrInfo()->get(II->getOpcode()); - if ((TID.isCall() && !TID.isReturn()) || + if ((MCID.isCall() && !MCID.isReturn()) || II->isStackAligningInlineAsm()) { MFI->setHasCalls(true); goto done; @@ -681,7 +681,7 @@ void SelectionDAGISel::PrepareEHLandingPad() { // landing pad can thus be detected via the MachineModuleInfo. MCSymbol *Label = MF->getMMI().addLandingPad(FuncInfo->MBB); - const TargetInstrDesc &II = TM.getInstrInfo()->get(TargetOpcode::EH_LABEL); + const MCInstrDesc &II = TM.getInstrInfo()->get(TargetOpcode::EH_LABEL); BuildMI(*FuncInfo->MBB, FuncInfo->InsertPt, SDB->getCurDebugLoc(), II) .addSym(Label); @@ -2613,9 +2613,9 @@ SelectCodeCommon(SDNode *NodeToMatch, const unsigned char *MatcherTable, if (EmitNodeInfo & OPFL_MemRefs) { // Only attach load or store memory operands if the generated // instruction may load or store. - const TargetInstrDesc &TID = TM.getInstrInfo()->get(TargetOpc); - bool mayLoad = TID.mayLoad(); - bool mayStore = TID.mayStore(); + const MCInstrDesc &MCID = TM.getInstrInfo()->get(TargetOpc); + bool mayLoad = MCID.mayLoad(); + bool mayStore = MCID.mayStore(); unsigned NumMemRefs = 0; for (SmallVector::const_iterator I = diff --git a/lib/CodeGen/StackSlotColoring.cpp b/lib/CodeGen/StackSlotColoring.cpp index aefaa10..57cbe1b 100644 --- a/lib/CodeGen/StackSlotColoring.cpp +++ b/lib/CodeGen/StackSlotColoring.cpp @@ -504,7 +504,7 @@ bool StackSlotColoring::PropagateBackward(MachineBasicBlock::iterator MII, bool FoundDef = false; // Not counting 2address def. Uses.clear(); - const TargetInstrDesc &TID = MII->getDesc(); + const MCInstrDesc &MCID = MII->getDesc(); for (unsigned i = 0, e = MII->getNumOperands(); i != e; ++i) { MachineOperand &MO = MII->getOperand(i); if (!MO.isReg()) @@ -521,7 +521,7 @@ bool StackSlotColoring::PropagateBackward(MachineBasicBlock::iterator MII, if (MO.getSubReg() || MII->isSubregToReg()) return false; - const TargetRegisterClass *RC = TII->getRegClass(TID, i, TRI); + const TargetRegisterClass *RC = TII->getRegClass(MCID, i, TRI); if (RC && !RC->contains(NewReg)) return false; @@ -566,7 +566,7 @@ bool StackSlotColoring::PropagateForward(MachineBasicBlock::iterator MII, SmallVector Uses; while (++MII != MBB->end()) { bool FoundKill = false; - const TargetInstrDesc &TID = MII->getDesc(); + const MCInstrDesc &MCID = MII->getDesc(); for (unsigned i = 0, e = MII->getNumOperands(); i != e; ++i) { MachineOperand &MO = MII->getOperand(i); if (!MO.isReg()) @@ -583,7 +583,7 @@ bool StackSlotColoring::PropagateForward(MachineBasicBlock::iterator MII, if (MO.getSubReg()) return false; - const TargetRegisterClass *RC = TII->getRegClass(TID, i, TRI); + const TargetRegisterClass *RC = TII->getRegClass(MCID, i, TRI); if (RC && !RC->contains(NewReg)) return false; if (MO.isKill()) diff --git a/lib/CodeGen/TailDuplication.cpp b/lib/CodeGen/TailDuplication.cpp index 906a6f5..6fe4bd7 100644 --- a/lib/CodeGen/TailDuplication.cpp +++ b/lib/CodeGen/TailDuplication.cpp @@ -529,8 +529,8 @@ TailDuplicatePass::shouldTailDuplicate(const MachineFunction &MF, bool hasIndirectBR = false; if (PreRegAlloc && !TailBB.empty()) { - const TargetInstrDesc &TID = TailBB.back().getDesc(); - if (TID.isIndirectBranch()) { + const MCInstrDesc &MCID = TailBB.back().getDesc(); + if (MCID.isIndirectBranch()) { MaxDuplicateCount = 20; hasIndirectBR = true; } diff --git a/lib/CodeGen/TargetInstrInfoImpl.cpp b/lib/CodeGen/TargetInstrInfoImpl.cpp index 34e2b33..86e71d8 100644 --- a/lib/CodeGen/TargetInstrInfoImpl.cpp +++ b/lib/CodeGen/TargetInstrInfoImpl.cpp @@ -59,8 +59,8 @@ TargetInstrInfoImpl::ReplaceTailWithBranchTo(MachineBasicBlock::iterator Tail, // the two operands returned by findCommutedOpIndices. MachineInstr *TargetInstrInfoImpl::commuteInstruction(MachineInstr *MI, bool NewMI) const { - const TargetInstrDesc &TID = MI->getDesc(); - bool HasDef = TID.getNumDefs(); + const MCInstrDesc &MCID = MI->getDesc(); + bool HasDef = MCID.getNumDefs(); if (HasDef && !MI->getOperand(0).isReg()) // No idea how to commute this instruction. Target should implement its own. return 0; @@ -81,7 +81,7 @@ MachineInstr *TargetInstrInfoImpl::commuteInstruction(MachineInstr *MI, bool ChangeReg0 = false; if (HasDef && MI->getOperand(0).getReg() == Reg1) { // Must be two address instruction! - assert(MI->getDesc().getOperandConstraint(0, TOI::TIED_TO) && + assert(MI->getDesc().getOperandConstraint(0, MCOI::TIED_TO) && "Expecting a two-address instruction!"); Reg2IsKill = false; ChangeReg0 = true; @@ -119,12 +119,12 @@ MachineInstr *TargetInstrInfoImpl::commuteInstruction(MachineInstr *MI, bool TargetInstrInfoImpl::findCommutedOpIndices(MachineInstr *MI, unsigned &SrcOpIdx1, unsigned &SrcOpIdx2) const { - const TargetInstrDesc &TID = MI->getDesc(); - if (!TID.isCommutable()) + const MCInstrDesc &MCID = MI->getDesc(); + if (!MCID.isCommutable()) return false; // This assumes v0 = op v1, v2 and commuting would swap v1 and v2. If this // is not true, then the target must implement this. - SrcOpIdx1 = TID.getNumDefs(); + SrcOpIdx1 = MCID.getNumDefs(); SrcOpIdx2 = SrcOpIdx1 + 1; if (!MI->getOperand(SrcOpIdx1).isReg() || !MI->getOperand(SrcOpIdx2).isReg()) @@ -137,12 +137,12 @@ bool TargetInstrInfoImpl::findCommutedOpIndices(MachineInstr *MI, bool TargetInstrInfoImpl::PredicateInstruction(MachineInstr *MI, const SmallVectorImpl &Pred) const { bool MadeChange = false; - const TargetInstrDesc &TID = MI->getDesc(); - if (!TID.isPredicable()) + const MCInstrDesc &MCID = MI->getDesc(); + if (!MCID.isPredicable()) return false; for (unsigned j = 0, i = 0, e = MI->getNumOperands(); i != e; ++i) { - if (TID.OpInfo[i].isPredicate()) { + if (MCID.OpInfo[i].isPredicate()) { MachineOperand &MO = MI->getOperand(i); if (MO.isReg()) { MO.setReg(Pred[j].getReg()); @@ -332,10 +332,10 @@ isReallyTriviallyReMaterializableGeneric(const MachineInstr *MI, MF.getFrameInfo()->isImmutableObjectIndex(FrameIdx)) return true; - const TargetInstrDesc &TID = MI->getDesc(); + const MCInstrDesc &MCID = MI->getDesc(); // Avoid instructions obviously unsafe for remat. - if (TID.isNotDuplicable() || TID.mayStore() || + if (MCID.isNotDuplicable() || MCID.mayStore() || MI->hasUnmodeledSideEffects()) return false; @@ -345,7 +345,7 @@ isReallyTriviallyReMaterializableGeneric(const MachineInstr *MI, return false; // Avoid instructions which load from potentially varying memory. - if (TID.mayLoad() && !MI->isInvariantLoad(AA)) + if (MCID.mayLoad() && !MI->isInvariantLoad(AA)) return false; // If any of the registers accessed are non-constant, conservatively assume diff --git a/lib/CodeGen/TwoAddressInstructionPass.cpp b/lib/CodeGen/TwoAddressInstructionPass.cpp index f1c0bb1..6d6244e 100644 --- a/lib/CodeGen/TwoAddressInstructionPass.cpp +++ b/lib/CodeGen/TwoAddressInstructionPass.cpp @@ -280,8 +280,8 @@ bool TwoAddressInstructionPass::Sink3AddrInstruction(MachineBasicBlock *MBB, /// isTwoAddrUse - Return true if the specified MI is using the specified /// register as a two-address operand. static bool isTwoAddrUse(MachineInstr *UseMI, unsigned Reg) { - const TargetInstrDesc &TID = UseMI->getDesc(); - for (unsigned i = 0, e = TID.getNumOperands(); i != e; ++i) { + const MCInstrDesc &MCID = UseMI->getDesc(); + for (unsigned i = 0, e = MCID.getNumOperands(); i != e; ++i) { MachineOperand &MO = UseMI->getOperand(i); if (MO.isReg() && MO.getReg() == Reg && (MO.isDef() || UseMI->isRegTiedToDefOperand(i))) @@ -443,8 +443,9 @@ static bool isKilled(MachineInstr &MI, unsigned Reg, /// isTwoAddrUse - Return true if the specified MI uses the specified register /// as a two-address use. If so, return the destination register by reference. static bool isTwoAddrUse(MachineInstr &MI, unsigned Reg, unsigned &DstReg) { - const TargetInstrDesc &TID = MI.getDesc(); - unsigned NumOps = MI.isInlineAsm() ? MI.getNumOperands():TID.getNumOperands(); + const MCInstrDesc &MCID = MI.getDesc(); + unsigned NumOps = MI.isInlineAsm() + ? MI.getNumOperands() : MCID.getNumOperands(); for (unsigned i = 0; i != NumOps; ++i) { const MachineOperand &MO = MI.getOperand(i); if (!MO.isReg() || !MO.isUse() || MO.getReg() != Reg) @@ -761,10 +762,10 @@ void TwoAddressInstructionPass::ProcessCopy(MachineInstr *MI, static bool isSafeToDelete(MachineInstr *MI, const TargetInstrInfo *TII, SmallVector &Kills) { - const TargetInstrDesc &TID = MI->getDesc(); - if (TID.mayStore() || TID.isCall()) + const MCInstrDesc &MCID = MI->getDesc(); + if (MCID.mayStore() || MCID.isCall()) return false; - if (TID.isTerminator() || MI->hasUnmodeledSideEffects()) + if (MCID.isTerminator() || MI->hasUnmodeledSideEffects()) return false; for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { @@ -854,7 +855,7 @@ TryInstructionTransform(MachineBasicBlock::iterator &mi, MachineFunction::iterator &mbbi, unsigned SrcIdx, unsigned DstIdx, unsigned Dist, SmallPtrSet &Processed) { - const TargetInstrDesc &TID = mi->getDesc(); + const MCInstrDesc &MCID = mi->getDesc(); unsigned regA = mi->getOperand(DstIdx).getReg(); unsigned regB = mi->getOperand(SrcIdx).getReg(); @@ -876,7 +877,7 @@ TryInstructionTransform(MachineBasicBlock::iterator &mi, unsigned regCIdx = ~0U; bool TryCommute = false; bool AggressiveCommute = false; - if (TID.isCommutable() && mi->getNumOperands() >= 3 && + if (MCID.isCommutable() && mi->getNumOperands() >= 3 && TII->findCommutedOpIndices(mi, SrcOp1, SrcOp2)) { if (SrcIdx == SrcOp1) regCIdx = SrcOp2; @@ -907,7 +908,7 @@ TryInstructionTransform(MachineBasicBlock::iterator &mi, if (TargetRegisterInfo::isVirtualRegister(regA)) ScanUses(regA, &*mbbi, Processed); - if (TID.isConvertibleTo3Addr()) { + if (MCID.isConvertibleTo3Addr()) { // This instruction is potentially convertible to a true // three-address instruction. Check if it is profitable. if (!regBKilled || isProfitableToConv3Addr(regA, regB)) { @@ -927,7 +928,7 @@ TryInstructionTransform(MachineBasicBlock::iterator &mi, // movq (%rax), %rcx // addq %rdx, %rcx // because it's preferable to schedule a load than a register copy. - if (TID.mayLoad() && !regBKilled) { + if (MCID.mayLoad() && !regBKilled) { // Determine if a load can be unfolded. unsigned LoadRegIndex; unsigned NewOpc = @@ -936,14 +937,14 @@ TryInstructionTransform(MachineBasicBlock::iterator &mi, /*UnfoldStore=*/false, &LoadRegIndex); if (NewOpc != 0) { - const TargetInstrDesc &UnfoldTID = TII->get(NewOpc); - if (UnfoldTID.getNumDefs() == 1) { + const MCInstrDesc &UnfoldMCID = TII->get(NewOpc); + if (UnfoldMCID.getNumDefs() == 1) { MachineFunction &MF = *mbbi->getParent(); // Unfold the load. DEBUG(dbgs() << "2addr: UNFOLDING: " << *mi); const TargetRegisterClass *RC = - TII->getRegClass(UnfoldTID, LoadRegIndex, TRI); + TII->getRegClass(UnfoldMCID, LoadRegIndex, TRI); unsigned Reg = MRI->createVirtualRegister(RC); SmallVector NewMIs; if (!TII->unfoldMemoryOperand(MF, mi, Reg, @@ -1067,7 +1068,7 @@ bool TwoAddressInstructionPass::runOnMachineFunction(MachineFunction &MF) { if (mi->isRegSequence()) RegSequences.push_back(&*mi); - const TargetInstrDesc &TID = mi->getDesc(); + const MCInstrDesc &MCID = mi->getDesc(); bool FirstTied = true; DistanceMap.insert(std::make_pair(mi, ++Dist)); @@ -1077,7 +1078,7 @@ bool TwoAddressInstructionPass::runOnMachineFunction(MachineFunction &MF) { // First scan through all the tied register uses in this instruction // and record a list of pairs of tied operands for each register. unsigned NumOps = mi->isInlineAsm() - ? mi->getNumOperands() : TID.getNumOperands(); + ? mi->getNumOperands() : MCID.getNumOperands(); for (unsigned SrcIdx = 0; SrcIdx < NumOps; ++SrcIdx) { unsigned DstIdx = 0; if (!mi->isRegTiedToDefOperand(SrcIdx, &DstIdx)) diff --git a/lib/CodeGen/VirtRegRewriter.cpp b/lib/CodeGen/VirtRegRewriter.cpp index 1850658..a5ec797 100644 --- a/lib/CodeGen/VirtRegRewriter.cpp +++ b/lib/CodeGen/VirtRegRewriter.cpp @@ -679,8 +679,8 @@ static void ReMaterialize(MachineBasicBlock &MBB, VirtRegMap &VRM) { MachineInstr *ReMatDefMI = VRM.getReMaterializedMI(Reg); #ifndef NDEBUG - const TargetInstrDesc &TID = ReMatDefMI->getDesc(); - assert(TID.getNumDefs() == 1 && + const MCInstrDesc &MCID = ReMatDefMI->getDesc(); + assert(MCID.getNumDefs() == 1 && "Don't know how to remat instructions that define > 1 values!"); #endif TII->reMaterialize(MBB, MII, DestReg, 0, ReMatDefMI, *TRI); @@ -1483,11 +1483,11 @@ OptimizeByUnfold(MachineBasicBlock::iterator &MII, /// where SrcReg is r1 and it is tied to r0. Return true if after /// commuting this instruction it will be r0 = op r2, r1. static bool CommuteChangesDestination(MachineInstr *DefMI, - const TargetInstrDesc &TID, + const MCInstrDesc &MCID, unsigned SrcReg, const TargetInstrInfo *TII, unsigned &DstIdx) { - if (TID.getNumDefs() != 1 && TID.getNumOperands() != 3) + if (MCID.getNumDefs() != 1 && MCID.getNumOperands() != 3) return false; if (!DefMI->getOperand(1).isReg() || DefMI->getOperand(1).getReg() != SrcReg) @@ -1527,11 +1527,11 @@ CommuteToFoldReload(MachineBasicBlock::iterator &MII, MachineInstr &MI = *MII; MachineBasicBlock::iterator DefMII = prior(MII); MachineInstr *DefMI = DefMII; - const TargetInstrDesc &TID = DefMI->getDesc(); + const MCInstrDesc &MCID = DefMI->getDesc(); unsigned NewDstIdx; if (DefMII != MBB->begin() && - TID.isCommutable() && - CommuteChangesDestination(DefMI, TID, SrcReg, TII, NewDstIdx)) { + MCID.isCommutable() && + CommuteChangesDestination(DefMI, MCID, SrcReg, TII, NewDstIdx)) { MachineOperand &NewDstMO = DefMI->getOperand(NewDstIdx); unsigned NewReg = NewDstMO.getReg(); if (!NewDstMO.isKill() || TRI->regsOverlap(NewReg, SrcReg)) @@ -1658,9 +1658,9 @@ SpillRegToStackSlot(MachineBasicBlock::iterator &MII, /// isSafeToDelete - Return true if this instruction doesn't produce any side /// effect and all of its defs are dead. static bool isSafeToDelete(MachineInstr &MI) { - const TargetInstrDesc &TID = MI.getDesc(); - if (TID.mayLoad() || TID.mayStore() || TID.isTerminator() || - TID.isCall() || TID.isBarrier() || TID.isReturn() || + const MCInstrDesc &MCID = MI.getDesc(); + if (MCID.mayLoad() || MCID.mayStore() || MCID.isTerminator() || + MCID.isCall() || MCID.isBarrier() || MCID.isReturn() || MI.isLabel() || MI.isDebugValue() || MI.hasUnmodeledSideEffects()) return false; diff --git a/lib/Target/ARM/ARMBaseInstrInfo.cpp b/lib/Target/ARM/ARMBaseInstrInfo.cpp index 44a3976..c619e8f 100644 --- a/lib/Target/ARM/ARMBaseInstrInfo.cpp +++ b/lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -136,9 +136,9 @@ ARMBaseInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI, MachineInstr *UpdateMI = NULL; MachineInstr *MemMI = NULL; unsigned AddrMode = (TSFlags & ARMII::AddrModeMask); - const TargetInstrDesc &TID = MI->getDesc(); - unsigned NumOps = TID.getNumOperands(); - bool isLoad = !TID.mayStore(); + const MCInstrDesc &MCID = MI->getDesc(); + unsigned NumOps = MCID.getNumOperands(); + bool isLoad = !MCID.mayStore(); const MachineOperand &WB = isLoad ? MI->getOperand(1) : MI->getOperand(0); const MachineOperand &Base = MI->getOperand(2); const MachineOperand &Offset = MI->getOperand(NumOps-3); @@ -475,8 +475,8 @@ SubsumesPredicate(const SmallVectorImpl &Pred1, bool ARMBaseInstrInfo::DefinesPredicate(MachineInstr *MI, std::vector &Pred) const { // FIXME: This confuses implicit_def with optional CPSR def. - const TargetInstrDesc &TID = MI->getDesc(); - if (!TID.getImplicitDefs() && !TID.hasOptionalDef()) + const MCInstrDesc &MCID = MI->getDesc(); + if (!MCID.getImplicitDefs() && !MCID.hasOptionalDef()) return false; bool Found = false; @@ -495,11 +495,11 @@ bool ARMBaseInstrInfo::DefinesPredicate(MachineInstr *MI, /// By default, this returns true for every instruction with a /// PredicateOperand. bool ARMBaseInstrInfo::isPredicable(MachineInstr *MI) const { - const TargetInstrDesc &TID = MI->getDesc(); - if (!TID.isPredicable()) + const MCInstrDesc &MCID = MI->getDesc(); + if (!MCID.isPredicable()) return false; - if ((TID.TSFlags & ARMII::DomainMask) == ARMII::DomainNEON) { + if ((MCID.TSFlags & ARMII::DomainMask) == ARMII::DomainNEON) { ARMFunctionInfo *AFI = MI->getParent()->getParent()->getInfo(); return AFI->isThumb2Function(); @@ -525,8 +525,8 @@ unsigned ARMBaseInstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const { const MCAsmInfo *MAI = MF->getTarget().getMCAsmInfo(); // Basic size info comes from the TSFlags field. - const TargetInstrDesc &TID = MI->getDesc(); - uint64_t TSFlags = TID.TSFlags; + const MCInstrDesc &MCID = MI->getDesc(); + uint64_t TSFlags = MCID.TSFlags; unsigned Opc = MI->getOpcode(); switch ((TSFlags & ARMII::SizeMask) >> ARMII::SizeShift) { @@ -588,9 +588,9 @@ unsigned ARMBaseInstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const { // entry is one byte; TBH two byte each. unsigned EntrySize = (Opc == ARM::t2TBB_JT) ? 1 : ((Opc == ARM::t2TBH_JT) ? 2 : 4); - unsigned NumOps = TID.getNumOperands(); + unsigned NumOps = MCID.getNumOperands(); MachineOperand JTOP = - MI->getOperand(NumOps - (TID.isPredicable() ? 3 : 2)); + MI->getOperand(NumOps - (MCID.isPredicable() ? 3 : 2)); unsigned JTI = JTOP.getIndex(); const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); assert(MJTI != 0); @@ -1363,7 +1363,7 @@ bool llvm::rewriteARMFrameIndex(MachineInstr &MI, unsigned FrameRegIdx, unsigned FrameReg, int &Offset, const ARMBaseInstrInfo &TII) { unsigned Opcode = MI.getOpcode(); - const TargetInstrDesc &Desc = MI.getDesc(); + const MCInstrDesc &Desc = MI.getDesc(); unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask); bool isSub = false; @@ -1803,7 +1803,7 @@ ARMBaseInstrInfo::getNumMicroOps(const InstrItineraryData *ItinData, if (!ItinData || ItinData->isEmpty()) return 1; - const TargetInstrDesc &Desc = MI->getDesc(); + const MCInstrDesc &Desc = MI->getDesc(); unsigned Class = Desc.getSchedClass(); unsigned UOps = ItinData->Itineraries[Class].NumMicroOps; if (UOps) @@ -1906,10 +1906,10 @@ ARMBaseInstrInfo::getNumMicroOps(const InstrItineraryData *ItinData, int ARMBaseInstrInfo::getVLDMDefCycle(const InstrItineraryData *ItinData, - const TargetInstrDesc &DefTID, + const MCInstrDesc &DefMCID, unsigned DefClass, unsigned DefIdx, unsigned DefAlign) const { - int RegNo = (int)(DefIdx+1) - DefTID.getNumOperands() + 1; + int RegNo = (int)(DefIdx+1) - DefMCID.getNumOperands() + 1; if (RegNo <= 0) // Def is the address writeback. return ItinData->getOperandCycle(DefClass, DefIdx); @@ -1924,7 +1924,7 @@ ARMBaseInstrInfo::getVLDMDefCycle(const InstrItineraryData *ItinData, DefCycle = RegNo; bool isSLoad = false; - switch (DefTID.getOpcode()) { + switch (DefMCID.getOpcode()) { default: break; case ARM::VLDMSIA: case ARM::VLDMSIA_UPD: @@ -1947,10 +1947,10 @@ ARMBaseInstrInfo::getVLDMDefCycle(const InstrItineraryData *ItinData, int ARMBaseInstrInfo::getLDMDefCycle(const InstrItineraryData *ItinData, - const TargetInstrDesc &DefTID, + const MCInstrDesc &DefMCID, unsigned DefClass, unsigned DefIdx, unsigned DefAlign) const { - int RegNo = (int)(DefIdx+1) - DefTID.getNumOperands() + 1; + int RegNo = (int)(DefIdx+1) - DefMCID.getNumOperands() + 1; if (RegNo <= 0) // Def is the address writeback. return ItinData->getOperandCycle(DefClass, DefIdx); @@ -1982,10 +1982,10 @@ ARMBaseInstrInfo::getLDMDefCycle(const InstrItineraryData *ItinData, int ARMBaseInstrInfo::getVSTMUseCycle(const InstrItineraryData *ItinData, - const TargetInstrDesc &UseTID, + const MCInstrDesc &UseMCID, unsigned UseClass, unsigned UseIdx, unsigned UseAlign) const { - int RegNo = (int)(UseIdx+1) - UseTID.getNumOperands() + 1; + int RegNo = (int)(UseIdx+1) - UseMCID.getNumOperands() + 1; if (RegNo <= 0) return ItinData->getOperandCycle(UseClass, UseIdx); @@ -1999,7 +1999,7 @@ ARMBaseInstrInfo::getVSTMUseCycle(const InstrItineraryData *ItinData, UseCycle = RegNo; bool isSStore = false; - switch (UseTID.getOpcode()) { + switch (UseMCID.getOpcode()) { default: break; case ARM::VSTMSIA: case ARM::VSTMSIA_UPD: @@ -2022,10 +2022,10 @@ ARMBaseInstrInfo::getVSTMUseCycle(const InstrItineraryData *ItinData, int ARMBaseInstrInfo::getSTMUseCycle(const InstrItineraryData *ItinData, - const TargetInstrDesc &UseTID, + const MCInstrDesc &UseMCID, unsigned UseClass, unsigned UseIdx, unsigned UseAlign) const { - int RegNo = (int)(UseIdx+1) - UseTID.getNumOperands() + 1; + int RegNo = (int)(UseIdx+1) - UseMCID.getNumOperands() + 1; if (RegNo <= 0) return ItinData->getOperandCycle(UseClass, UseIdx); @@ -2051,14 +2051,14 @@ ARMBaseInstrInfo::getSTMUseCycle(const InstrItineraryData *ItinData, int ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, - const TargetInstrDesc &DefTID, + const MCInstrDesc &DefMCID, unsigned DefIdx, unsigned DefAlign, - const TargetInstrDesc &UseTID, + const MCInstrDesc &UseMCID, unsigned UseIdx, unsigned UseAlign) const { - unsigned DefClass = DefTID.getSchedClass(); - unsigned UseClass = UseTID.getSchedClass(); + unsigned DefClass = DefMCID.getSchedClass(); + unsigned UseClass = UseMCID.getSchedClass(); - if (DefIdx < DefTID.getNumDefs() && UseIdx < UseTID.getNumOperands()) + if (DefIdx < DefMCID.getNumDefs() && UseIdx < UseMCID.getNumOperands()) return ItinData->getOperandLatency(DefClass, DefIdx, UseClass, UseIdx); // This may be a def / use of a variable_ops instruction, the operand @@ -2066,7 +2066,7 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, // figure it out. int DefCycle = -1; bool LdmBypass = false; - switch (DefTID.getOpcode()) { + switch (DefMCID.getOpcode()) { default: DefCycle = ItinData->getOperandCycle(DefClass, DefIdx); break; @@ -2077,7 +2077,7 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, case ARM::VLDMSIA: case ARM::VLDMSIA_UPD: case ARM::VLDMSDB_UPD: - DefCycle = getVLDMDefCycle(ItinData, DefTID, DefClass, DefIdx, DefAlign); + DefCycle = getVLDMDefCycle(ItinData, DefMCID, DefClass, DefIdx, DefAlign); break; case ARM::LDMIA_RET: @@ -2098,7 +2098,7 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, case ARM::t2LDMIA_UPD: case ARM::t2LDMDB_UPD: LdmBypass = 1; - DefCycle = getLDMDefCycle(ItinData, DefTID, DefClass, DefIdx, DefAlign); + DefCycle = getLDMDefCycle(ItinData, DefMCID, DefClass, DefIdx, DefAlign); break; } @@ -2107,7 +2107,7 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, DefCycle = 2; int UseCycle = -1; - switch (UseTID.getOpcode()) { + switch (UseMCID.getOpcode()) { default: UseCycle = ItinData->getOperandCycle(UseClass, UseIdx); break; @@ -2118,7 +2118,7 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, case ARM::VSTMSIA: case ARM::VSTMSIA_UPD: case ARM::VSTMSDB_UPD: - UseCycle = getVSTMUseCycle(ItinData, UseTID, UseClass, UseIdx, UseAlign); + UseCycle = getVSTMUseCycle(ItinData, UseMCID, UseClass, UseIdx, UseAlign); break; case ARM::STMIA: @@ -2137,7 +2137,7 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, case ARM::t2STMDB: case ARM::t2STMIA_UPD: case ARM::t2STMDB_UPD: - UseCycle = getSTMUseCycle(ItinData, UseTID, UseClass, UseIdx, UseAlign); + UseCycle = getSTMUseCycle(ItinData, UseMCID, UseClass, UseIdx, UseAlign); break; } @@ -2150,7 +2150,7 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, if (LdmBypass) { // It's a variable_ops instruction so we can't use DefIdx here. Just use // first def operand. - if (ItinData->hasPipelineForwarding(DefClass, DefTID.getNumOperands()-1, + if (ItinData->hasPipelineForwarding(DefClass, DefMCID.getNumOperands()-1, UseClass, UseIdx)) --UseCycle; } else if (ItinData->hasPipelineForwarding(DefClass, DefIdx, @@ -2170,11 +2170,11 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, DefMI->isRegSequence() || DefMI->isImplicitDef()) return 1; - const TargetInstrDesc &DefTID = DefMI->getDesc(); + const MCInstrDesc &DefMCID = DefMI->getDesc(); if (!ItinData || ItinData->isEmpty()) - return DefTID.mayLoad() ? 3 : 1; + return DefMCID.mayLoad() ? 3 : 1; - const TargetInstrDesc &UseTID = UseMI->getDesc(); + const MCInstrDesc &UseMCID = UseMI->getDesc(); const MachineOperand &DefMO = DefMI->getOperand(DefIdx); if (DefMO.getReg() == ARM::CPSR) { if (DefMI->getOpcode() == ARM::FMSTAT) { @@ -2183,7 +2183,7 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, } // CPSR set and branch can be paired in the same cycle. - if (UseTID.isBranch()) + if (UseMCID.isBranch()) return 0; } @@ -2191,14 +2191,14 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, ? (*DefMI->memoperands_begin())->getAlignment() : 0; unsigned UseAlign = UseMI->hasOneMemOperand() ? (*UseMI->memoperands_begin())->getAlignment() : 0; - int Latency = getOperandLatency(ItinData, DefTID, DefIdx, DefAlign, - UseTID, UseIdx, UseAlign); + int Latency = getOperandLatency(ItinData, DefMCID, DefIdx, DefAlign, + UseMCID, UseIdx, UseAlign); if (Latency > 1 && (Subtarget.isCortexA8() || Subtarget.isCortexA9())) { // FIXME: Shifter op hack: no shift (i.e. [r +/- r]) or [r + r << 2] // variants are one cycle cheaper. - switch (DefTID.getOpcode()) { + switch (DefMCID.getOpcode()) { default: break; case ARM::LDRrs: case ARM::LDRBrs: { @@ -2223,7 +2223,7 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, } if (DefAlign < 8 && Subtarget.isCortexA9()) - switch (DefTID.getOpcode()) { + switch (DefMCID.getOpcode()) { default: break; case ARM::VLD1q8: case ARM::VLD1q16: @@ -2327,37 +2327,37 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, if (!DefNode->isMachineOpcode()) return 1; - const TargetInstrDesc &DefTID = get(DefNode->getMachineOpcode()); + const MCInstrDesc &DefMCID = get(DefNode->getMachineOpcode()); - if (isZeroCost(DefTID.Opcode)) + if (isZeroCost(DefMCID.Opcode)) return 0; if (!ItinData || ItinData->isEmpty()) - return DefTID.mayLoad() ? 3 : 1; + return DefMCID.mayLoad() ? 3 : 1; if (!UseNode->isMachineOpcode()) { - int Latency = ItinData->getOperandCycle(DefTID.getSchedClass(), DefIdx); + int Latency = ItinData->getOperandCycle(DefMCID.getSchedClass(), DefIdx); if (Subtarget.isCortexA9()) return Latency <= 2 ? 1 : Latency - 1; else return Latency <= 3 ? 1 : Latency - 2; } - const TargetInstrDesc &UseTID = get(UseNode->getMachineOpcode()); + const MCInstrDesc &UseMCID = get(UseNode->getMachineOpcode()); const MachineSDNode *DefMN = dyn_cast(DefNode); unsigned DefAlign = !DefMN->memoperands_empty() ? (*DefMN->memoperands_begin())->getAlignment() : 0; const MachineSDNode *UseMN = dyn_cast(UseNode); unsigned UseAlign = !UseMN->memoperands_empty() ? (*UseMN->memoperands_begin())->getAlignment() : 0; - int Latency = getOperandLatency(ItinData, DefTID, DefIdx, DefAlign, - UseTID, UseIdx, UseAlign); + int Latency = getOperandLatency(ItinData, DefMCID, DefIdx, DefAlign, + UseMCID, UseIdx, UseAlign); if (Latency > 1 && (Subtarget.isCortexA8() || Subtarget.isCortexA9())) { // FIXME: Shifter op hack: no shift (i.e. [r +/- r]) or [r + r << 2] // variants are one cycle cheaper. - switch (DefTID.getOpcode()) { + switch (DefMCID.getOpcode()) { default: break; case ARM::LDRrs: case ARM::LDRBrs: { @@ -2384,7 +2384,7 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, } if (DefAlign < 8 && Subtarget.isCortexA9()) - switch (DefTID.getOpcode()) { + switch (DefMCID.getOpcode()) { default: break; case ARM::VLD1q8Pseudo: case ARM::VLD1q16Pseudo: @@ -2503,10 +2503,10 @@ int ARMBaseInstrInfo::getInstrLatency(const InstrItineraryData *ItinData, if (!ItinData || ItinData->isEmpty()) return 1; - const TargetInstrDesc &TID = MI->getDesc(); - unsigned Class = TID.getSchedClass(); + const MCInstrDesc &MCID = MI->getDesc(); + unsigned Class = MCID.getSchedClass(); unsigned UOps = ItinData->Itineraries[Class].NumMicroOps; - if (PredCost && TID.hasImplicitDefOfPhysReg(ARM::CPSR)) + if (PredCost && MCID.hasImplicitDefOfPhysReg(ARM::CPSR)) // When predicated, CPSR is an additional source operand for CPSR updating // instructions, this apparently increases their latencies. *PredCost = 1; diff --git a/lib/Target/ARM/ARMBaseInstrInfo.h b/lib/Target/ARM/ARMBaseInstrInfo.h index 96f0e76..ab93cde 100644 --- a/lib/Target/ARM/ARMBaseInstrInfo.h +++ b/lib/Target/ARM/ARMBaseInstrInfo.h @@ -353,25 +353,25 @@ public: SDNode *UseNode, unsigned UseIdx) const; private: int getVLDMDefCycle(const InstrItineraryData *ItinData, - const TargetInstrDesc &DefTID, + const MCInstrDesc &DefMCID, unsigned DefClass, unsigned DefIdx, unsigned DefAlign) const; int getLDMDefCycle(const InstrItineraryData *ItinData, - const TargetInstrDesc &DefTID, + const MCInstrDesc &DefMCID, unsigned DefClass, unsigned DefIdx, unsigned DefAlign) const; int getVSTMUseCycle(const InstrItineraryData *ItinData, - const TargetInstrDesc &UseTID, + const MCInstrDesc &UseMCID, unsigned UseClass, unsigned UseIdx, unsigned UseAlign) const; int getSTMUseCycle(const InstrItineraryData *ItinData, - const TargetInstrDesc &UseTID, + const MCInstrDesc &UseMCID, unsigned UseClass, unsigned UseIdx, unsigned UseAlign) const; int getOperandLatency(const InstrItineraryData *ItinData, - const TargetInstrDesc &DefTID, + const MCInstrDesc &DefMCID, unsigned DefIdx, unsigned DefAlign, - const TargetInstrDesc &UseTID, + const MCInstrDesc &UseMCID, unsigned UseIdx, unsigned UseAlign) const; int getInstrLatency(const InstrItineraryData *ItinData, diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/lib/Target/ARM/ARMBaseRegisterInfo.cpp index b765476..8f10343 100644 --- a/lib/Target/ARM/ARMBaseRegisterInfo.cpp +++ b/lib/Target/ARM/ARMBaseRegisterInfo.cpp @@ -960,7 +960,7 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, int64_t ARMBaseRegisterInfo:: getFrameIndexInstrOffset(const MachineInstr *MI, int Idx) const { - const TargetInstrDesc &Desc = MI->getDesc(); + const MCInstrDesc &Desc = MI->getDesc(); unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask); int64_t InstrOffs = 0;; int Scale = 1; @@ -1110,11 +1110,11 @@ materializeFrameBaseRegister(MachineBasicBlock *MBB, if (Ins != MBB->end()) DL = Ins->getDebugLoc(); - const TargetInstrDesc &TID = TII.get(ADDriOpc); + const MCInstrDesc &MCID = TII.get(ADDriOpc); MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo(); - MRI.constrainRegClass(BaseReg, TII.getRegClass(TID, 0, this)); + MRI.constrainRegClass(BaseReg, TII.getRegClass(MCID, 0, this)); - MachineInstrBuilder MIB = BuildMI(*MBB, Ins, DL, TID, BaseReg) + MachineInstrBuilder MIB = BuildMI(*MBB, Ins, DL, MCID, BaseReg) .addFrameIndex(FrameIdx).addImm(Offset); if (!AFI->isThumb1OnlyFunction()) @@ -1150,7 +1150,7 @@ ARMBaseRegisterInfo::resolveFrameIndex(MachineBasicBlock::iterator I, bool ARMBaseRegisterInfo::isFrameOffsetLegal(const MachineInstr *MI, int64_t Offset) const { - const TargetInstrDesc &Desc = MI->getDesc(); + const MCInstrDesc &Desc = MI->getDesc(); unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask); unsigned i = 0; diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp index 16d4ca5..d6fca62 100644 --- a/lib/Target/ARM/ARMCodeEmitter.cpp +++ b/lib/Target/ARM/ARMCodeEmitter.cpp @@ -96,13 +96,13 @@ namespace { void addPCLabel(unsigned LabelID); void emitPseudoInstruction(const MachineInstr &MI); unsigned getMachineSoRegOpValue(const MachineInstr &MI, - const TargetInstrDesc &TID, + const MCInstrDesc &MCID, const MachineOperand &MO, unsigned OpIdx); unsigned getMachineSoImmOpValue(unsigned SoImm); unsigned getAddrModeSBit(const MachineInstr &MI, - const TargetInstrDesc &TID) const; + const MCInstrDesc &MCID) const; void emitDataProcessingInstruction(const MachineInstr &MI, unsigned ImplicitRd = 0, @@ -443,9 +443,9 @@ unsigned ARMCodeEmitter::getMachineOpValue(const MachineInstr &MI, else if (MO.isSymbol()) emitExternalSymbolAddress(MO.getSymbolName(), ARM::reloc_arm_branch); else if (MO.isCPI()) { - const TargetInstrDesc &TID = MI.getDesc(); + const MCInstrDesc &MCID = MI.getDesc(); // For VFP load, the immediate offset is multiplied by 4. - unsigned Reloc = ((TID.TSFlags & ARMII::FormMask) == ARMII::VFPLdStFrm) + unsigned Reloc = ((MCID.TSFlags & ARMII::FormMask) == ARMII::VFPLdStFrm) ? ARM::reloc_arm_vfp_cp_entry : ARM::reloc_arm_cp_entry; emitConstPoolAddress(MO.getIndex(), Reloc); } else if (MO.isJTI()) @@ -757,7 +757,7 @@ void ARMCodeEmitter::emitMOVi2piecesInstruction(const MachineInstr &MI) { void ARMCodeEmitter::emitLEApcrelJTInstruction(const MachineInstr &MI) { // It's basically add r, pc, (LJTI - $+8) - const TargetInstrDesc &TID = MI.getDesc(); + const MCInstrDesc &MCID = MI.getDesc(); // Emit the 'add' instruction. unsigned Binary = 0x4 << 21; // add: Insts{24-21} = 0b0100 @@ -766,7 +766,7 @@ void ARMCodeEmitter::emitLEApcrelJTInstruction(const MachineInstr &MI) { Binary |= II->getPredicate(&MI) << ARMII::CondShift; // Encode S bit if MI modifies CPSR. - Binary |= getAddrModeSBit(MI, TID); + Binary |= getAddrModeSBit(MI, MCID); // Encode Rd. Binary |= getMachineOpValue(MI, 0) << ARMII::RegRdShift; @@ -912,7 +912,7 @@ void ARMCodeEmitter::emitPseudoInstruction(const MachineInstr &MI) { } unsigned ARMCodeEmitter::getMachineSoRegOpValue(const MachineInstr &MI, - const TargetInstrDesc &TID, + const MCInstrDesc &MCID, const MachineOperand &MO, unsigned OpIdx) { unsigned Binary = getMachineOpValue(MI, MO); @@ -982,8 +982,8 @@ unsigned ARMCodeEmitter::getMachineSoImmOpValue(unsigned SoImm) { } unsigned ARMCodeEmitter::getAddrModeSBit(const MachineInstr &MI, - const TargetInstrDesc &TID) const { - for (unsigned i = MI.getNumOperands(), e = TID.getNumOperands(); i >= e; --i){ + const MCInstrDesc &MCID) const { + for (unsigned i = MI.getNumOperands(), e = MCID.getNumOperands(); i >= e; --i){ const MachineOperand &MO = MI.getOperand(i-1); if (MO.isReg() && MO.isDef() && MO.getReg() == ARM::CPSR) return 1 << ARMII::S_BitShift; @@ -994,7 +994,7 @@ unsigned ARMCodeEmitter::getAddrModeSBit(const MachineInstr &MI, void ARMCodeEmitter::emitDataProcessingInstruction(const MachineInstr &MI, unsigned ImplicitRd, unsigned ImplicitRn) { - const TargetInstrDesc &TID = MI.getDesc(); + const MCInstrDesc &MCID = MI.getDesc(); // Part of binary is determined by TableGn. unsigned Binary = getBinaryCodeForInstr(MI); @@ -1003,10 +1003,10 @@ void ARMCodeEmitter::emitDataProcessingInstruction(const MachineInstr &MI, Binary |= II->getPredicate(&MI) << ARMII::CondShift; // Encode S bit if MI modifies CPSR. - Binary |= getAddrModeSBit(MI, TID); + Binary |= getAddrModeSBit(MI, MCID); // Encode register def if there is one. - unsigned NumDefs = TID.getNumDefs(); + unsigned NumDefs = MCID.getNumDefs(); unsigned OpIdx = 0; if (NumDefs) Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRdShift; @@ -1014,7 +1014,7 @@ void ARMCodeEmitter::emitDataProcessingInstruction(const MachineInstr &MI, // Special handling for implicit use (e.g. PC). Binary |= (getARMRegisterNumbering(ImplicitRd) << ARMII::RegRdShift); - if (TID.Opcode == ARM::MOVi16) { + if (MCID.Opcode == ARM::MOVi16) { // Get immediate from MI. unsigned Lo16 = getMovi32Value(MI, MI.getOperand(OpIdx), ARM::reloc_arm_movw); @@ -1023,14 +1023,14 @@ void ARMCodeEmitter::emitDataProcessingInstruction(const MachineInstr &MI, Binary |= ((Lo16 >> 12) & 0xF) << 16; emitWordLE(Binary); return; - } else if(TID.Opcode == ARM::MOVTi16) { + } else if(MCID.Opcode == ARM::MOVTi16) { unsigned Hi16 = (getMovi32Value(MI, MI.getOperand(OpIdx), ARM::reloc_arm_movt) >> 16); Binary |= Hi16 & 0xFFF; Binary |= ((Hi16 >> 12) & 0xF) << 16; emitWordLE(Binary); return; - } else if ((TID.Opcode == ARM::BFC) || (TID.Opcode == ARM::BFI)) { + } else if ((MCID.Opcode == ARM::BFC) || (MCID.Opcode == ARM::BFI)) { uint32_t v = ~MI.getOperand(2).getImm(); int32_t lsb = CountTrailingZeros_32(v); int32_t msb = (32 - CountLeadingZeros_32(v)) - 1; @@ -1039,7 +1039,7 @@ void ARMCodeEmitter::emitDataProcessingInstruction(const MachineInstr &MI, Binary |= (lsb & 0x1F) << 7; emitWordLE(Binary); return; - } else if ((TID.Opcode == ARM::UBFX) || (TID.Opcode == ARM::SBFX)) { + } else if ((MCID.Opcode == ARM::UBFX) || (MCID.Opcode == ARM::SBFX)) { // Encode Rn in Instr{0-3} Binary |= getMachineOpValue(MI, OpIdx++); @@ -1054,11 +1054,11 @@ void ARMCodeEmitter::emitDataProcessingInstruction(const MachineInstr &MI, } // If this is a two-address operand, skip it. e.g. MOVCCr operand 1. - if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) + if (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1) ++OpIdx; // Encode first non-shifter register operand if there is one. - bool isUnary = TID.TSFlags & ARMII::UnaryDP; + bool isUnary = MCID.TSFlags & ARMII::UnaryDP; if (!isUnary) { if (ImplicitRn) // Special handling for implicit use (e.g. PC). @@ -1071,9 +1071,9 @@ void ARMCodeEmitter::emitDataProcessingInstruction(const MachineInstr &MI, // Encode shifter operand. const MachineOperand &MO = MI.getOperand(OpIdx); - if ((TID.TSFlags & ARMII::FormMask) == ARMII::DPSoRegFrm) { + if ((MCID.TSFlags & ARMII::FormMask) == ARMII::DPSoRegFrm) { // Encode SoReg. - emitWordLE(Binary | getMachineSoRegOpValue(MI, TID, MO, OpIdx)); + emitWordLE(Binary | getMachineSoRegOpValue(MI, MCID, MO, OpIdx)); return; } @@ -1092,9 +1092,9 @@ void ARMCodeEmitter::emitDataProcessingInstruction(const MachineInstr &MI, void ARMCodeEmitter::emitLoadStoreInstruction(const MachineInstr &MI, unsigned ImplicitRd, unsigned ImplicitRn) { - const TargetInstrDesc &TID = MI.getDesc(); - unsigned Form = TID.TSFlags & ARMII::FormMask; - bool IsPrePost = (TID.TSFlags & ARMII::IndexModeMask) != 0; + const MCInstrDesc &MCID = MI.getDesc(); + unsigned Form = MCID.TSFlags & ARMII::FormMask; + bool IsPrePost = (MCID.TSFlags & ARMII::IndexModeMask) != 0; // Part of binary is determined by TableGn. unsigned Binary = getBinaryCodeForInstr(MI); @@ -1134,7 +1134,7 @@ void ARMCodeEmitter::emitLoadStoreInstruction(const MachineInstr &MI, Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRnShift; // If this is a two-address operand, skip it. e.g. LDR_PRE. - if (!Skipped && TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) + if (!Skipped && MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1) ++OpIdx; const MachineOperand &MO2 = MI.getOperand(OpIdx); @@ -1170,9 +1170,9 @@ void ARMCodeEmitter::emitLoadStoreInstruction(const MachineInstr &MI, void ARMCodeEmitter::emitMiscLoadStoreInstruction(const MachineInstr &MI, unsigned ImplicitRn) { - const TargetInstrDesc &TID = MI.getDesc(); - unsigned Form = TID.TSFlags & ARMII::FormMask; - bool IsPrePost = (TID.TSFlags & ARMII::IndexModeMask) != 0; + const MCInstrDesc &MCID = MI.getDesc(); + unsigned Form = MCID.TSFlags & ARMII::FormMask; + bool IsPrePost = (MCID.TSFlags & ARMII::IndexModeMask) != 0; // Part of binary is determined by TableGn. unsigned Binary = getBinaryCodeForInstr(MI); @@ -1194,7 +1194,7 @@ void ARMCodeEmitter::emitMiscLoadStoreInstruction(const MachineInstr &MI, Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRdShift; // Skip LDRD and STRD's second operand. - if (TID.Opcode == ARM::LDRD || TID.Opcode == ARM::STRD) + if (MCID.Opcode == ARM::LDRD || MCID.Opcode == ARM::STRD) ++OpIdx; // Set second operand @@ -1205,7 +1205,7 @@ void ARMCodeEmitter::emitMiscLoadStoreInstruction(const MachineInstr &MI, Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRnShift; // If this is a two-address operand, skip it. e.g. LDRH_POST. - if (!Skipped && TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) + if (!Skipped && MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1) ++OpIdx; const MachineOperand &MO2 = MI.getOperand(OpIdx); @@ -1255,8 +1255,8 @@ static unsigned getAddrModeUPBits(unsigned Mode) { } void ARMCodeEmitter::emitLoadStoreMultipleInstruction(const MachineInstr &MI) { - const TargetInstrDesc &TID = MI.getDesc(); - bool IsUpdating = (TID.TSFlags & ARMII::IndexModeMask) != 0; + const MCInstrDesc &MCID = MI.getDesc(); + bool IsUpdating = (MCID.TSFlags & ARMII::IndexModeMask) != 0; // Part of binary is determined by TableGn. unsigned Binary = getBinaryCodeForInstr(MI); @@ -1295,7 +1295,7 @@ void ARMCodeEmitter::emitLoadStoreMultipleInstruction(const MachineInstr &MI) { } void ARMCodeEmitter::emitMulFrmInstruction(const MachineInstr &MI) { - const TargetInstrDesc &TID = MI.getDesc(); + const MCInstrDesc &MCID = MI.getDesc(); // Part of binary is determined by TableGn. unsigned Binary = getBinaryCodeForInstr(MI); @@ -1304,12 +1304,12 @@ void ARMCodeEmitter::emitMulFrmInstruction(const MachineInstr &MI) { Binary |= II->getPredicate(&MI) << ARMII::CondShift; // Encode S bit if MI modifies CPSR. - Binary |= getAddrModeSBit(MI, TID); + Binary |= getAddrModeSBit(MI, MCID); // 32x32->64bit operations have two destination registers. The number // of register definitions will tell us if that's what we're dealing with. unsigned OpIdx = 0; - if (TID.getNumDefs() == 2) + if (MCID.getNumDefs() == 2) Binary |= getMachineOpValue (MI, OpIdx++) << ARMII::RegRdLoShift; // Encode Rd @@ -1323,16 +1323,16 @@ void ARMCodeEmitter::emitMulFrmInstruction(const MachineInstr &MI) { // Many multiple instructions (e.g. MLA) have three src operands. Encode // it as Rn (for multiply, that's in the same offset as RdLo. - if (TID.getNumOperands() > OpIdx && - !TID.OpInfo[OpIdx].isPredicate() && - !TID.OpInfo[OpIdx].isOptionalDef()) + if (MCID.getNumOperands() > OpIdx && + !MCID.OpInfo[OpIdx].isPredicate() && + !MCID.OpInfo[OpIdx].isOptionalDef()) Binary |= getMachineOpValue(MI, OpIdx) << ARMII::RegRdLoShift; emitWordLE(Binary); } void ARMCodeEmitter::emitExtendInstruction(const MachineInstr &MI) { - const TargetInstrDesc &TID = MI.getDesc(); + const MCInstrDesc &MCID = MI.getDesc(); // Part of binary is determined by TableGn. unsigned Binary = getBinaryCodeForInstr(MI); @@ -1361,15 +1361,15 @@ void ARMCodeEmitter::emitExtendInstruction(const MachineInstr &MI) { // Encode rot imm (0, 8, 16, or 24) if it has a rotate immediate operand. if (MI.getOperand(OpIdx).isImm() && - !TID.OpInfo[OpIdx].isPredicate() && - !TID.OpInfo[OpIdx].isOptionalDef()) + !MCID.OpInfo[OpIdx].isPredicate() && + !MCID.OpInfo[OpIdx].isOptionalDef()) Binary |= (getMachineOpValue(MI, OpIdx) / 8) << ARMII::ExtRotImmShift; emitWordLE(Binary); } void ARMCodeEmitter::emitMiscArithInstruction(const MachineInstr &MI) { - const TargetInstrDesc &TID = MI.getDesc(); + const MCInstrDesc &MCID = MI.getDesc(); // Part of binary is determined by TableGn. unsigned Binary = getBinaryCodeForInstr(MI); @@ -1378,7 +1378,7 @@ void ARMCodeEmitter::emitMiscArithInstruction(const MachineInstr &MI) { Binary |= II->getPredicate(&MI) << ARMII::CondShift; // PKH instructions are finished at this point - if (TID.Opcode == ARM::PKHBT || TID.Opcode == ARM::PKHTB) { + if (MCID.Opcode == ARM::PKHBT || MCID.Opcode == ARM::PKHTB) { emitWordLE(Binary); return; } @@ -1389,9 +1389,9 @@ void ARMCodeEmitter::emitMiscArithInstruction(const MachineInstr &MI) { Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRdShift; const MachineOperand &MO = MI.getOperand(OpIdx++); - if (OpIdx == TID.getNumOperands() || - TID.OpInfo[OpIdx].isPredicate() || - TID.OpInfo[OpIdx].isOptionalDef()) { + if (OpIdx == MCID.getNumOperands() || + MCID.OpInfo[OpIdx].isPredicate() || + MCID.OpInfo[OpIdx].isOptionalDef()) { // Encode Rm and it's done. Binary |= getMachineOpValue(MI, MO); emitWordLE(Binary); @@ -1406,7 +1406,7 @@ void ARMCodeEmitter::emitMiscArithInstruction(const MachineInstr &MI) { // Encode shift_imm. unsigned ShiftAmt = MI.getOperand(OpIdx).getImm(); - if (TID.Opcode == ARM::PKHTB) { + if (MCID.Opcode == ARM::PKHTB) { assert(ShiftAmt != 0 && "PKHTB shift_imm is 0!"); if (ShiftAmt == 32) ShiftAmt = 0; @@ -1418,7 +1418,7 @@ void ARMCodeEmitter::emitMiscArithInstruction(const MachineInstr &MI) { } void ARMCodeEmitter::emitSaturateInstruction(const MachineInstr &MI) { - const TargetInstrDesc &TID = MI.getDesc(); + const MCInstrDesc &MCID = MI.getDesc(); // Part of binary is determined by TableGen. unsigned Binary = getBinaryCodeForInstr(MI); @@ -1431,11 +1431,11 @@ void ARMCodeEmitter::emitSaturateInstruction(const MachineInstr &MI) { // Encode saturate bit position. unsigned Pos = MI.getOperand(1).getImm(); - if (TID.Opcode == ARM::SSAT || TID.Opcode == ARM::SSAT16) + if (MCID.Opcode == ARM::SSAT || MCID.Opcode == ARM::SSAT16) Pos -= 1; assert((Pos < 16 || (Pos < 32 && - TID.Opcode != ARM::SSAT16 && - TID.Opcode != ARM::USAT16)) && + MCID.Opcode != ARM::SSAT16 && + MCID.Opcode != ARM::USAT16)) && "saturate bit position out of range"); Binary |= Pos << 16; @@ -1443,7 +1443,7 @@ void ARMCodeEmitter::emitSaturateInstruction(const MachineInstr &MI) { Binary |= getMachineOpValue(MI, 2); // Encode shift_imm. - if (TID.getNumOperands() == 4) { + if (MCID.getNumOperands() == 4) { unsigned ShiftOp = MI.getOperand(3).getImm(); ARM_AM::ShiftOpc Opc = ARM_AM::getSORegShOp(ShiftOp); if (Opc == ARM_AM::asr) @@ -1459,9 +1459,9 @@ void ARMCodeEmitter::emitSaturateInstruction(const MachineInstr &MI) { } void ARMCodeEmitter::emitBranchInstruction(const MachineInstr &MI) { - const TargetInstrDesc &TID = MI.getDesc(); + const MCInstrDesc &MCID = MI.getDesc(); - if (TID.Opcode == ARM::TPsoft) { + if (MCID.Opcode == ARM::TPsoft) { llvm_unreachable("ARM::TPsoft FIXME"); // FIXME } @@ -1498,20 +1498,20 @@ void ARMCodeEmitter::emitInlineJumpTable(unsigned JTIndex) { } void ARMCodeEmitter::emitMiscBranchInstruction(const MachineInstr &MI) { - const TargetInstrDesc &TID = MI.getDesc(); + const MCInstrDesc &MCID = MI.getDesc(); // Handle jump tables. - if (TID.Opcode == ARM::BR_JTr || TID.Opcode == ARM::BR_JTadd) { + if (MCID.Opcode == ARM::BR_JTr || MCID.Opcode == ARM::BR_JTadd) { // First emit a ldr pc, [] instruction. emitDataProcessingInstruction(MI, ARM::PC); // Then emit the inline jump table. unsigned JTIndex = - (TID.Opcode == ARM::BR_JTr) + (MCID.Opcode == ARM::BR_JTr) ? MI.getOperand(1).getIndex() : MI.getOperand(2).getIndex(); emitInlineJumpTable(JTIndex); return; - } else if (TID.Opcode == ARM::BR_JTm) { + } else if (MCID.Opcode == ARM::BR_JTm) { // First emit a ldr pc, [] instruction. emitLoadStoreInstruction(MI, ARM::PC); @@ -1526,7 +1526,7 @@ void ARMCodeEmitter::emitMiscBranchInstruction(const MachineInstr &MI) { // Set the conditional execution predicate Binary |= II->getPredicate(&MI) << ARMII::CondShift; - if (TID.Opcode == ARM::BX_RET || TID.Opcode == ARM::MOVPCLR) + if (MCID.Opcode == ARM::BX_RET || MCID.Opcode == ARM::MOVPCLR) // The return register is LR. Binary |= getARMRegisterNumbering(ARM::LR); else @@ -1579,7 +1579,7 @@ static unsigned encodeVFPRm(const MachineInstr &MI, unsigned OpIdx) { } void ARMCodeEmitter::emitVFPArithInstruction(const MachineInstr &MI) { - const TargetInstrDesc &TID = MI.getDesc(); + const MCInstrDesc &MCID = MI.getDesc(); // Part of binary is determined by TableGn. unsigned Binary = getBinaryCodeForInstr(MI); @@ -1596,16 +1596,16 @@ void ARMCodeEmitter::emitVFPArithInstruction(const MachineInstr &MI) { Binary |= encodeVFPRd(MI, OpIdx++); // If this is a two-address operand, skip it, e.g. FMACD. - if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) + if (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1) ++OpIdx; // Encode Dn / Sn. - if ((TID.TSFlags & ARMII::FormMask) == ARMII::VFPBinaryFrm) + if ((MCID.TSFlags & ARMII::FormMask) == ARMII::VFPBinaryFrm) Binary |= encodeVFPRn(MI, OpIdx++); - if (OpIdx == TID.getNumOperands() || - TID.OpInfo[OpIdx].isPredicate() || - TID.OpInfo[OpIdx].isOptionalDef()) { + if (OpIdx == MCID.getNumOperands() || + MCID.OpInfo[OpIdx].isPredicate() || + MCID.OpInfo[OpIdx].isOptionalDef()) { // FCMPEZD etc. has only one operand. emitWordLE(Binary); return; @@ -1618,8 +1618,8 @@ void ARMCodeEmitter::emitVFPArithInstruction(const MachineInstr &MI) { } void ARMCodeEmitter::emitVFPConversionInstruction(const MachineInstr &MI) { - const TargetInstrDesc &TID = MI.getDesc(); - unsigned Form = TID.TSFlags & ARMII::FormMask; + const MCInstrDesc &MCID = MI.getDesc(); + unsigned Form = MCID.TSFlags & ARMII::FormMask; // Part of binary is determined by TableGn. unsigned Binary = getBinaryCodeForInstr(MI); @@ -1709,8 +1709,8 @@ void ARMCodeEmitter::emitVFPLoadStoreInstruction(const MachineInstr &MI) { void ARMCodeEmitter::emitVFPLoadStoreMultipleInstruction(const MachineInstr &MI) { - const TargetInstrDesc &TID = MI.getDesc(); - bool IsUpdating = (TID.TSFlags & ARMII::IndexModeMask) != 0; + const MCInstrDesc &MCID = MI.getDesc(); + bool IsUpdating = (MCID.TSFlags & ARMII::IndexModeMask) != 0; // Part of binary is determined by TableGn. unsigned Binary = getBinaryCodeForInstr(MI); @@ -1795,8 +1795,8 @@ void ARMCodeEmitter::emitNEONLaneInstruction(const MachineInstr &MI) { unsigned Binary = getBinaryCodeForInstr(MI); unsigned RegTOpIdx, RegNOpIdx, LnOpIdx; - const TargetInstrDesc &TID = MI.getDesc(); - if ((TID.TSFlags & ARMII::FormMask) == ARMII::NGetLnFrm) { + const MCInstrDesc &MCID = MI.getDesc(); + if ((MCID.TSFlags & ARMII::FormMask) == ARMII::NGetLnFrm) { RegTOpIdx = 0; RegNOpIdx = 1; LnOpIdx = 2; @@ -1863,12 +1863,12 @@ void ARMCodeEmitter::emitNEON1RegModImmInstruction(const MachineInstr &MI) { } void ARMCodeEmitter::emitNEON2RegInstruction(const MachineInstr &MI) { - const TargetInstrDesc &TID = MI.getDesc(); + const MCInstrDesc &MCID = MI.getDesc(); unsigned Binary = getBinaryCodeForInstr(MI); // Destination register is encoded in Dd; source register in Dm. unsigned OpIdx = 0; Binary |= encodeNEONRd(MI, OpIdx++); - if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) + if (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1) ++OpIdx; Binary |= encodeNEONRm(MI, OpIdx); if (IsThumb) @@ -1878,15 +1878,15 @@ void ARMCodeEmitter::emitNEON2RegInstruction(const MachineInstr &MI) { } void ARMCodeEmitter::emitNEON3RegInstruction(const MachineInstr &MI) { - const TargetInstrDesc &TID = MI.getDesc(); + const MCInstrDesc &MCID = MI.getDesc(); unsigned Binary = getBinaryCodeForInstr(MI); // Destination register is encoded in Dd; source registers in Dn and Dm. unsigned OpIdx = 0; Binary |= encodeNEONRd(MI, OpIdx++); - if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) + if (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1) ++OpIdx; Binary |= encodeNEONRn(MI, OpIdx++); - if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) + if (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1) ++OpIdx; Binary |= encodeNEONRm(MI, OpIdx); if (IsThumb) diff --git a/lib/Target/ARM/ARMConstantIslandPass.cpp b/lib/Target/ARM/ARMConstantIslandPass.cpp index baf95a3..309caee 100644 --- a/lib/Target/ARM/ARMConstantIslandPass.cpp +++ b/lib/Target/ARM/ARMConstantIslandPass.cpp @@ -1692,9 +1692,9 @@ bool ARMConstantIslands::OptimizeThumb2JumpTables(MachineFunction &MF) { const std::vector &JT = MJTI->getJumpTables(); for (unsigned i = 0, e = T2JumpTables.size(); i != e; ++i) { MachineInstr *MI = T2JumpTables[i]; - const TargetInstrDesc &TID = MI->getDesc(); - unsigned NumOps = TID.getNumOperands(); - unsigned JTOpIdx = NumOps - (TID.isPredicable() ? 3 : 2); + const MCInstrDesc &MCID = MI->getDesc(); + unsigned NumOps = MCID.getNumOperands(); + unsigned JTOpIdx = NumOps - (MCID.isPredicable() ? 3 : 2); MachineOperand JTOP = MI->getOperand(JTOpIdx); unsigned JTI = JTOP.getIndex(); assert(JTI < JT.size()); @@ -1815,9 +1815,9 @@ bool ARMConstantIslands::ReorderThumb2JumpTables(MachineFunction &MF) { const std::vector &JT = MJTI->getJumpTables(); for (unsigned i = 0, e = T2JumpTables.size(); i != e; ++i) { MachineInstr *MI = T2JumpTables[i]; - const TargetInstrDesc &TID = MI->getDesc(); - unsigned NumOps = TID.getNumOperands(); - unsigned JTOpIdx = NumOps - (TID.isPredicable() ? 3 : 2); + const MCInstrDesc &MCID = MI->getDesc(); + unsigned NumOps = MCID.getNumOperands(); + unsigned JTOpIdx = NumOps - (MCID.isPredicable() ? 3 : 2); MachineOperand JTOP = MI->getOperand(JTOpIdx); unsigned JTI = JTOP.getIndex(); assert(JTI < JT.size()); diff --git a/lib/Target/ARM/ARMExpandPseudoInsts.cpp b/lib/Target/ARM/ARMExpandPseudoInsts.cpp index b6b3c75..71b33d3 100644 --- a/lib/Target/ARM/ARMExpandPseudoInsts.cpp +++ b/lib/Target/ARM/ARMExpandPseudoInsts.cpp @@ -68,7 +68,7 @@ namespace { void ARMExpandPseudo::TransferImpOps(MachineInstr &OldMI, MachineInstrBuilder &UseMI, MachineInstrBuilder &DefMI) { - const TargetInstrDesc &Desc = OldMI.getDesc(); + const MCInstrDesc &Desc = OldMI.getDesc(); for (unsigned i = Desc.getNumOperands(), e = OldMI.getNumOperands(); i != e; ++i) { const MachineOperand &MO = OldMI.getOperand(i); diff --git a/lib/Target/ARM/ARMFastISel.cpp b/lib/Target/ARM/ARMFastISel.cpp index 5cf73c4..e0409e9 100644 --- a/lib/Target/ARM/ARMFastISel.cpp +++ b/lib/Target/ARM/ARMFastISel.cpp @@ -219,8 +219,8 @@ class ARMFastISel : public FastISel { // we don't care about implicit defs here, just places we'll need to add a // default CCReg argument. Sets CPSR if we're setting CPSR instead of CCR. bool ARMFastISel::DefinesOptionalPredicate(MachineInstr *MI, bool *CPSR) { - const TargetInstrDesc &TID = MI->getDesc(); - if (!TID.hasOptionalDef()) + const MCInstrDesc &MCID = MI->getDesc(); + if (!MCID.hasOptionalDef()) return false; // Look to see if our OptionalDef is defining CPSR or CCR. @@ -234,15 +234,15 @@ bool ARMFastISel::DefinesOptionalPredicate(MachineInstr *MI, bool *CPSR) { } bool ARMFastISel::isARMNEONPred(const MachineInstr *MI) { - const TargetInstrDesc &TID = MI->getDesc(); + const MCInstrDesc &MCID = MI->getDesc(); // If we're a thumb2 or not NEON function we were handled via isPredicable. - if ((TID.TSFlags & ARMII::DomainMask) != ARMII::DomainNEON || + if ((MCID.TSFlags & ARMII::DomainMask) != ARMII::DomainNEON || AFI->isThumb2Function()) return false; - for (unsigned i = 0, e = TID.getNumOperands(); i != e; ++i) - if (TID.OpInfo[i].isPredicate()) + for (unsigned i = 0, e = MCID.getNumOperands(); i != e; ++i) + if (MCID.OpInfo[i].isPredicate()) return true; return false; @@ -278,7 +278,7 @@ ARMFastISel::AddOptionalDefs(const MachineInstrBuilder &MIB) { unsigned ARMFastISel::FastEmitInst_(unsigned MachineInstOpcode, const TargetRegisterClass* RC) { unsigned ResultReg = createResultReg(RC); - const TargetInstrDesc &II = TII.get(MachineInstOpcode); + const MCInstrDesc &II = TII.get(MachineInstOpcode); AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg)); return ResultReg; @@ -288,7 +288,7 @@ unsigned ARMFastISel::FastEmitInst_r(unsigned MachineInstOpcode, const TargetRegisterClass *RC, unsigned Op0, bool Op0IsKill) { unsigned ResultReg = createResultReg(RC); - const TargetInstrDesc &II = TII.get(MachineInstOpcode); + const MCInstrDesc &II = TII.get(MachineInstOpcode); if (II.getNumDefs() >= 1) AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) @@ -308,7 +308,7 @@ unsigned ARMFastISel::FastEmitInst_rr(unsigned MachineInstOpcode, unsigned Op0, bool Op0IsKill, unsigned Op1, bool Op1IsKill) { unsigned ResultReg = createResultReg(RC); - const TargetInstrDesc &II = TII.get(MachineInstOpcode); + const MCInstrDesc &II = TII.get(MachineInstOpcode); if (II.getNumDefs() >= 1) AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) @@ -331,7 +331,7 @@ unsigned ARMFastISel::FastEmitInst_rrr(unsigned MachineInstOpcode, unsigned Op1, bool Op1IsKill, unsigned Op2, bool Op2IsKill) { unsigned ResultReg = createResultReg(RC); - const TargetInstrDesc &II = TII.get(MachineInstOpcode); + const MCInstrDesc &II = TII.get(MachineInstOpcode); if (II.getNumDefs() >= 1) AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) @@ -355,7 +355,7 @@ unsigned ARMFastISel::FastEmitInst_ri(unsigned MachineInstOpcode, unsigned Op0, bool Op0IsKill, uint64_t Imm) { unsigned ResultReg = createResultReg(RC); - const TargetInstrDesc &II = TII.get(MachineInstOpcode); + const MCInstrDesc &II = TII.get(MachineInstOpcode); if (II.getNumDefs() >= 1) AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) @@ -377,7 +377,7 @@ unsigned ARMFastISel::FastEmitInst_rf(unsigned MachineInstOpcode, unsigned Op0, bool Op0IsKill, const ConstantFP *FPImm) { unsigned ResultReg = createResultReg(RC); - const TargetInstrDesc &II = TII.get(MachineInstOpcode); + const MCInstrDesc &II = TII.get(MachineInstOpcode); if (II.getNumDefs() >= 1) AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) @@ -400,7 +400,7 @@ unsigned ARMFastISel::FastEmitInst_rri(unsigned MachineInstOpcode, unsigned Op1, bool Op1IsKill, uint64_t Imm) { unsigned ResultReg = createResultReg(RC); - const TargetInstrDesc &II = TII.get(MachineInstOpcode); + const MCInstrDesc &II = TII.get(MachineInstOpcode); if (II.getNumDefs() >= 1) AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) @@ -423,7 +423,7 @@ unsigned ARMFastISel::FastEmitInst_i(unsigned MachineInstOpcode, const TargetRegisterClass *RC, uint64_t Imm) { unsigned ResultReg = createResultReg(RC); - const TargetInstrDesc &II = TII.get(MachineInstOpcode); + const MCInstrDesc &II = TII.get(MachineInstOpcode); if (II.getNumDefs() >= 1) AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) @@ -442,7 +442,7 @@ unsigned ARMFastISel::FastEmitInst_ii(unsigned MachineInstOpcode, const TargetRegisterClass *RC, uint64_t Imm1, uint64_t Imm2) { unsigned ResultReg = createResultReg(RC); - const TargetInstrDesc &II = TII.get(MachineInstOpcode); + const MCInstrDesc &II = TII.get(MachineInstOpcode); if (II.getNumDefs() >= 1) AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) diff --git a/lib/Target/ARM/ARMHazardRecognizer.cpp b/lib/Target/ARM/ARMHazardRecognizer.cpp index 517bba8..787f6a2 100644 --- a/lib/Target/ARM/ARMHazardRecognizer.cpp +++ b/lib/Target/ARM/ARMHazardRecognizer.cpp @@ -19,11 +19,11 @@ using namespace llvm; static bool hasRAWHazard(MachineInstr *DefMI, MachineInstr *MI, const TargetRegisterInfo &TRI) { // FIXME: Detect integer instructions properly. - const TargetInstrDesc &TID = MI->getDesc(); - unsigned Domain = TID.TSFlags & ARMII::DomainMask; - if (TID.mayStore()) + const MCInstrDesc &MCID = MI->getDesc(); + unsigned Domain = MCID.TSFlags & ARMII::DomainMask; + if (MCID.mayStore()) return false; - unsigned Opcode = TID.getOpcode(); + unsigned Opcode = MCID.getOpcode(); if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD) return false; if ((Domain & ARMII::DomainVFP) || (Domain & ARMII::DomainNEON)) @@ -43,15 +43,15 @@ ARMHazardRecognizer::getHazardType(SUnit *SU, int Stalls) { // Look for special VMLA / VMLS hazards. A VMUL / VADD / VSUB following // a VMLA / VMLS will cause 4 cycle stall. - const TargetInstrDesc &TID = MI->getDesc(); - if (LastMI && (TID.TSFlags & ARMII::DomainMask) != ARMII::DomainGeneral) { + const MCInstrDesc &MCID = MI->getDesc(); + if (LastMI && (MCID.TSFlags & ARMII::DomainMask) != ARMII::DomainGeneral) { MachineInstr *DefMI = LastMI; - const TargetInstrDesc &LastTID = LastMI->getDesc(); + const MCInstrDesc &LastMCID = LastMI->getDesc(); // Skip over one non-VFP / NEON instruction. - if (!LastTID.isBarrier() && + if (!LastMCID.isBarrier() && // On A9, AGU and NEON/FPU are muxed. - !(STI.isCortexA9() && (LastTID.mayLoad() || LastTID.mayStore())) && - (LastTID.TSFlags & ARMII::DomainMask) == ARMII::DomainGeneral) { + !(STI.isCortexA9() && (LastMCID.mayLoad() || LastMCID.mayStore())) && + (LastMCID.TSFlags & ARMII::DomainMask) == ARMII::DomainGeneral) { MachineBasicBlock::iterator I = LastMI; if (I != LastMI->getParent()->begin()) { I = llvm::prior(I); diff --git a/lib/Target/ARM/ARMISelDAGToDAG.cpp b/lib/Target/ARM/ARMISelDAGToDAG.cpp index 6f57a04..2c9481b 100644 --- a/lib/Target/ARM/ARMISelDAGToDAG.cpp +++ b/lib/Target/ARM/ARMISelDAGToDAG.cpp @@ -329,10 +329,10 @@ bool ARMDAGToDAGISel::hasNoVMLxHazardUse(SDNode *N) const { if (Use->getOpcode() == ISD::CopyToReg) return true; if (Use->isMachineOpcode()) { - const TargetInstrDesc &TID = TII->get(Use->getMachineOpcode()); - if (TID.mayStore()) + const MCInstrDesc &MCID = TII->get(Use->getMachineOpcode()); + if (MCID.mayStore()) return true; - unsigned Opcode = TID.getOpcode(); + unsigned Opcode = MCID.getOpcode(); if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD) return true; // vmlx feeding into another vmlx. We actually want to unfold diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index 9c01446..b0425f1 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -977,12 +977,12 @@ Sched::Preference ARMTargetLowering::getSchedulingPreference(SDNode *N) const { // Load are scheduled for latency even if there instruction itinerary // is not available. const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); - const TargetInstrDesc &TID = TII->get(N->getMachineOpcode()); + const MCInstrDesc &MCID = TII->get(N->getMachineOpcode()); - if (TID.getNumDefs() == 0) + if (MCID.getNumDefs() == 0) return Sched::RegPressure; if (!Itins->isEmpty() && - Itins->getOperandCycle(TID.getSchedClass(), 0) > 2) + Itins->getOperandCycle(MCID.getSchedClass(), 0) > 2) return Sched::Latency; return Sched::RegPressure; diff --git a/lib/Target/ARM/ARMLoadStoreOptimizer.cpp b/lib/Target/ARM/ARMLoadStoreOptimizer.cpp index e4ec681..c843382 100644 --- a/lib/Target/ARM/ARMLoadStoreOptimizer.cpp +++ b/lib/Target/ARM/ARMLoadStoreOptimizer.cpp @@ -1461,19 +1461,19 @@ static bool IsSafeAndProfitableToMove(bool isLd, unsigned Base, while (++I != E) { if (I->isDebugValue() || MemOps.count(&*I)) continue; - const TargetInstrDesc &TID = I->getDesc(); - if (TID.isCall() || TID.isTerminator() || I->hasUnmodeledSideEffects()) + const MCInstrDesc &MCID = I->getDesc(); + if (MCID.isCall() || MCID.isTerminator() || I->hasUnmodeledSideEffects()) return false; - if (isLd && TID.mayStore()) + if (isLd && MCID.mayStore()) return false; if (!isLd) { - if (TID.mayLoad()) + if (MCID.mayLoad()) return false; // It's not safe to move the first 'str' down. // str r1, [r0] // strh r5, [r0] // str r4, [r0, #+4] - if (TID.mayStore()) + if (MCID.mayStore()) return false; } for (unsigned j = 0, NumOps = I->getNumOperands(); j != NumOps; ++j) { @@ -1672,14 +1672,14 @@ bool ARMPreAllocLoadStoreOpt::RescheduleOps(MachineBasicBlock *MBB, Ops.pop_back(); Ops.pop_back(); - const TargetInstrDesc &TID = TII->get(NewOpc); - const TargetRegisterClass *TRC = TII->getRegClass(TID, 0, TRI); + const MCInstrDesc &MCID = TII->get(NewOpc); + const TargetRegisterClass *TRC = TII->getRegClass(MCID, 0, TRI); MRI->constrainRegClass(EvenReg, TRC); MRI->constrainRegClass(OddReg, TRC); // Form the pair instruction. if (isLd) { - MachineInstrBuilder MIB = BuildMI(*MBB, InsertPos, dl, TID) + MachineInstrBuilder MIB = BuildMI(*MBB, InsertPos, dl, MCID) .addReg(EvenReg, RegState::Define) .addReg(OddReg, RegState::Define) .addReg(BaseReg); @@ -1691,7 +1691,7 @@ bool ARMPreAllocLoadStoreOpt::RescheduleOps(MachineBasicBlock *MBB, MIB.addImm(Offset).addImm(Pred).addReg(PredReg); ++NumLDRDFormed; } else { - MachineInstrBuilder MIB = BuildMI(*MBB, InsertPos, dl, TID) + MachineInstrBuilder MIB = BuildMI(*MBB, InsertPos, dl, MCID) .addReg(EvenReg) .addReg(OddReg) .addReg(BaseReg); @@ -1742,8 +1742,8 @@ ARMPreAllocLoadStoreOpt::RescheduleLoadStoreInstrs(MachineBasicBlock *MBB) { while (MBBI != E) { for (; MBBI != E; ++MBBI) { MachineInstr *MI = MBBI; - const TargetInstrDesc &TID = MI->getDesc(); - if (TID.isCall() || TID.isTerminator()) { + const MCInstrDesc &MCID = MI->getDesc(); + if (MCID.isCall() || MCID.isTerminator()) { // Stop at barriers. ++MBBI; break; diff --git a/lib/Target/ARM/ARMMCCodeEmitter.cpp b/lib/Target/ARM/ARMMCCodeEmitter.cpp index c5f727d..4fcba11 100644 --- a/lib/Target/ARM/ARMMCCodeEmitter.cpp +++ b/lib/Target/ARM/ARMMCCodeEmitter.cpp @@ -1274,7 +1274,7 @@ void ARMMCCodeEmitter:: EncodeInstruction(const MCInst &MI, raw_ostream &OS, SmallVectorImpl &Fixups) const { // Pseudo instructions don't get encoded. - const TargetInstrDesc &Desc = TII.get(MI.getOpcode()); + const MCInstrDesc &Desc = TII.get(MI.getOpcode()); uint64_t TSFlags = Desc.TSFlags; if ((TSFlags & ARMII::FormMask) == ARMII::Pseudo) return; diff --git a/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp b/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp index 271ca8c..851b2d0 100644 --- a/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp +++ b/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp @@ -24,8 +24,8 @@ //#define DEBUG(X) do { X; } while (0) /// ARMGenInstrInfo.inc - ARMGenInstrInfo.inc contains the static const -/// TargetInstrDesc ARMInsts[] definition and the TargetOperandInfo[]'s -/// describing the operand info for each ARMInsts[i]. +/// MCInstrDesc ARMInsts[] definition and the MCOperandInfo[]'s describing the +/// operand info for each ARMInsts[i]. /// /// Together with an instruction's encoding format, we can take advantage of the /// NumOperands and the OpInfo fields of the target instruction description in @@ -46,10 +46,10 @@ /// dag DefaultOps = (ops (i32 14), (i32 zero_reg)); /// } /// -/// which is manifested by the TargetOperandInfo[] of: +/// which is manifested by the MCOperandInfo[] of: /// -/// { 0, 0|(1<> ARMII::IndexModeShift; + (MCID.TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift; unsigned Offset = ARM_AM::getAM2Opc(AddrOpcode, slice(insn, 7, 0) << 2, ARM_AM::no_shift, IndexMode); MI.addOperand(MCOperand::CreateImm(Offset)); @@ -802,7 +802,7 @@ static bool DisassembleBrFrm(MCInst &MI, unsigned Opcode, uint32_t insn, if (CoprocessorOpcode(Opcode)) return DisassembleCoprocessor(MI, Opcode, insn, NumOps, NumOpsAdded, B); - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; if (!OpInfo) return false; // MRS and MRSsys take one GPR reg Rd. @@ -901,7 +901,7 @@ static bool DisassembleBrFrm(MCInst &MI, unsigned Opcode, uint32_t insn, static bool DisassembleBrMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; if (!OpInfo) return false; unsigned &OpIdx = NumOpsAdded; @@ -976,10 +976,10 @@ static bool BadRegsDPFrm(unsigned Opcode, uint32_t insn) { static bool DisassembleDPFrm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetInstrDesc &TID = ARMInsts[Opcode]; - unsigned short NumDefs = TID.getNumDefs(); - bool isUnary = isUnaryDP(TID.TSFlags); - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opcode]; + unsigned short NumDefs = MCID.getNumDefs(); + bool isUnary = isUnaryDP(MCID.TSFlags); + const MCOperandInfo *OpInfo = MCID.OpInfo; unsigned &OpIdx = NumOpsAdded; OpIdx = 0; @@ -1041,7 +1041,7 @@ static bool DisassembleDPFrm(MCInst &MI, unsigned Opcode, uint32_t insn, } // If this is a two-address operand, skip it, e.g., MOVCCr operand 1. - if (isUnary && (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1)) { + if (isUnary && (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1)) { MI.addOperand(MCOperand::CreateReg(0)); ++OpIdx; } @@ -1089,10 +1089,10 @@ static bool DisassembleDPFrm(MCInst &MI, unsigned Opcode, uint32_t insn, static bool DisassembleDPSoRegFrm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetInstrDesc &TID = ARMInsts[Opcode]; - unsigned short NumDefs = TID.getNumDefs(); - bool isUnary = isUnaryDP(TID.TSFlags); - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opcode]; + unsigned short NumDefs = MCID.getNumDefs(); + bool isUnary = isUnaryDP(MCID.TSFlags); + const MCOperandInfo *OpInfo = MCID.OpInfo; unsigned &OpIdx = NumOpsAdded; OpIdx = 0; @@ -1118,7 +1118,7 @@ static bool DisassembleDPSoRegFrm(MCInst &MI, unsigned Opcode, uint32_t insn, } // If this is a two-address operand, skip it, e.g., MOVCCs operand 1. - if (isUnary && (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1)) { + if (isUnary && (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1)) { MI.addOperand(MCOperand::CreateReg(0)); ++OpIdx; } @@ -1244,17 +1244,17 @@ static bool BadRegsLdStFrm(unsigned Opcode, uint32_t insn, bool Store, bool WBac static bool DisassembleLdStFrm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, bool isStore, BO B) { - const TargetInstrDesc &TID = ARMInsts[Opcode]; - bool isPrePost = isPrePostLdSt(TID.TSFlags); - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opcode]; + bool isPrePost = isPrePostLdSt(MCID.TSFlags); + const MCOperandInfo *OpInfo = MCID.OpInfo; if (!OpInfo) return false; unsigned &OpIdx = NumOpsAdded; OpIdx = 0; - assert(((!isStore && TID.getNumDefs() > 0) || - (isStore && (TID.getNumDefs() == 0 || isPrePost))) + assert(((!isStore && MCID.getNumDefs() > 0) || + (isStore && (MCID.getNumDefs() == 0 || isPrePost))) && "Invalid arguments"); // Operand 0 of a pre- and post-indexed store is the address base writeback. @@ -1291,7 +1291,7 @@ static bool DisassembleLdStFrm(MCInst &MI, unsigned Opcode, uint32_t insn, assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID && "Reg operand expected"); - assert((!isPrePost || (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1)) + assert((!isPrePost || (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1)) && "Index mode or tied_to operand expected"); MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, decodeRn(insn)))); @@ -1308,7 +1308,7 @@ static bool DisassembleLdStFrm(MCInst &MI, unsigned Opcode, uint32_t insn, ARM_AM::AddrOpc AddrOpcode = getUBit(insn) ? ARM_AM::add : ARM_AM::sub; unsigned IndexMode = - (TID.TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift; + (MCID.TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift; if (getIBit(insn) == 0) { // For pre- and post-indexed case, add a reg0 operand (Addressing Mode #2). // Otherwise, skip the reg operand since for addrmode_imm12, Rn has already @@ -1379,17 +1379,17 @@ static bool HasDualReg(unsigned Opcode) { static bool DisassembleLdStMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, bool isStore, BO B) { - const TargetInstrDesc &TID = ARMInsts[Opcode]; - bool isPrePost = isPrePostLdSt(TID.TSFlags); - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opcode]; + bool isPrePost = isPrePostLdSt(MCID.TSFlags); + const MCOperandInfo *OpInfo = MCID.OpInfo; if (!OpInfo) return false; unsigned &OpIdx = NumOpsAdded; OpIdx = 0; - assert(((!isStore && TID.getNumDefs() > 0) || - (isStore && (TID.getNumDefs() == 0 || isPrePost))) + assert(((!isStore && MCID.getNumDefs() > 0) || + (isStore && (MCID.getNumDefs() == 0 || isPrePost))) && "Invalid arguments"); // Operand 0 of a pre- and post-indexed store is the address base writeback. @@ -1433,7 +1433,7 @@ static bool DisassembleLdStMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn, assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID && "Reg operand expected"); - assert((!isPrePost || (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1)) + assert((!isPrePost || (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1)) && "Offset mode or tied_to operand expected"); MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, decodeRn(insn)))); @@ -1451,7 +1451,7 @@ static bool DisassembleLdStMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn, ARM_AM::AddrOpc AddrOpcode = getUBit(insn) ? ARM_AM::add : ARM_AM::sub; unsigned IndexMode = - (TID.TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift; + (MCID.TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift; if (getAM3IBit(insn) == 1) { MI.addOperand(MCOperand::CreateReg(0)); @@ -1539,7 +1539,7 @@ static bool DisassembleLdStMulFrm(MCInst &MI, unsigned Opcode, uint32_t insn, static bool DisassembleLdStExFrm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; if (!OpInfo) return false; unsigned &OpIdx = NumOpsAdded; @@ -1591,7 +1591,7 @@ static bool DisassembleLdStExFrm(MCInst &MI, unsigned Opcode, uint32_t insn, static bool DisassembleArithMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; unsigned &OpIdx = NumOpsAdded; OpIdx = 0; @@ -1653,8 +1653,8 @@ static bool DisassembleSatFrm(MCInst &MI, unsigned Opcode, uint32_t insn, if (decodeRd(insn) == 15 || decodeRm(insn) == 15) return false; - const TargetInstrDesc &TID = ARMInsts[Opcode]; - NumOpsAdded = TID.getNumOperands() - 2; // ignore predicate operands + const MCInstrDesc &MCID = ARMInsts[Opcode]; + NumOpsAdded = MCID.getNumOperands() - 2; // ignore predicate operands // Disassemble register def. MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, @@ -1696,7 +1696,7 @@ static bool DisassembleExtFrm(MCInst &MI, unsigned Opcode, uint32_t insn, if (decodeRd(insn) == 15 || decodeRm(insn) == 15) return false; - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; unsigned &OpIdx = NumOpsAdded; OpIdx = 0; @@ -1802,7 +1802,7 @@ static bool DisassembleVFPUnaryFrm(MCInst &MI, unsigned Opcode, uint32_t insn, assert(NumOps >= 1 && "VFPUnaryFrm expects NumOps >= 1"); - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; unsigned &OpIdx = NumOpsAdded; OpIdx = 0; @@ -1842,8 +1842,8 @@ static bool DisassembleVFPBinaryFrm(MCInst &MI, unsigned Opcode, uint32_t insn, assert(NumOps >= 3 && "VFPBinaryFrm expects NumOps >= 3"); - const TargetInstrDesc &TID = ARMInsts[Opcode]; - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opcode]; + const MCOperandInfo *OpInfo = MCID.OpInfo; unsigned &OpIdx = NumOpsAdded; OpIdx = 0; @@ -1858,7 +1858,7 @@ static bool DisassembleVFPBinaryFrm(MCInst &MI, unsigned Opcode, uint32_t insn, ++OpIdx; // Skip tied_to operand constraint. - if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) { + if (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1) { assert(NumOps >= 4 && "Expect >=4 operands"); MI.addOperand(MCOperand::CreateReg(0)); ++OpIdx; @@ -1886,8 +1886,8 @@ static bool DisassembleVFPConv1Frm(MCInst &MI, unsigned Opcode, uint32_t insn, assert(NumOps >= 2 && "VFPConv1Frm expects NumOps >= 2"); - const TargetInstrDesc &TID = ARMInsts[Opcode]; - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opcode]; + const MCOperandInfo *OpInfo = MCID.OpInfo; if (!OpInfo) return false; bool SP = slice(insn, 8, 8) == 0; // A8.6.295 & A8.6.297 @@ -1903,7 +1903,7 @@ static bool DisassembleVFPConv1Frm(MCInst &MI, unsigned Opcode, uint32_t insn, getRegisterEnum(B, RegClassID, decodeVFPRd(insn, SP)))); - assert(TID.getOperandConstraint(1, TOI::TIED_TO) != -1 && + assert(MCID.getOperandConstraint(1, MCOI::TIED_TO) != -1 && "Tied to operand expected"); MI.addOperand(MI.getOperand(0)); @@ -1961,7 +1961,7 @@ static bool DisassembleVFPConv3Frm(MCInst &MI, unsigned Opcode, uint32_t insn, assert(NumOps >= 3 && "VFPConv3Frm expects NumOps >= 3"); - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; unsigned &OpIdx = NumOpsAdded; MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, @@ -2011,7 +2011,7 @@ static bool DisassembleVFPConv5Frm(MCInst &MI, unsigned Opcode, uint32_t insn, assert(NumOps >= 3 && "VFPConv5Frm expects NumOps >= 3"); - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; unsigned &OpIdx = NumOpsAdded; OpIdx = 0; @@ -2136,7 +2136,7 @@ static bool DisassembleVFPLdStMulFrm(MCInst &MI, unsigned Opcode, uint32_t insn, static bool DisassembleVFPMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; unsigned &OpIdx = NumOpsAdded; OpIdx = 0; @@ -2402,8 +2402,8 @@ static bool DisassembleNLdSt0(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, bool Store, bool DblSpaced, unsigned alignment, BO B) { - const TargetInstrDesc &TID = ARMInsts[Opcode]; - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opcode]; + const MCOperandInfo *OpInfo = MCID.OpInfo; // At least one DPR register plus addressing mode #6. assert(NumOps >= 3 && "Expect >= 3 operands"); @@ -2507,7 +2507,7 @@ static bool DisassembleNLdSt0(MCInst &MI, unsigned Opcode, uint32_t insn, } while (OpIdx < NumOps && (unsigned)OpInfo[OpIdx].RegClass == RegClass) { - assert(TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1 && + assert(MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1 && "Tied to operand expected"); MI.addOperand(MCOperand::CreateReg(0)); ++OpIdx; @@ -2757,8 +2757,8 @@ static bool DisassembleNLdSt(MCInst &MI, unsigned Opcode, uint32_t insn, static bool DisassembleN1RegModImmFrm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetInstrDesc &TID = ARMInsts[Opcode]; - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opcode]; + const MCOperandInfo *OpInfo = MCID.OpInfo; assert(NumOps >= 2 && (OpInfo[0].RegClass == ARM::DPRRegClassID || @@ -2848,8 +2848,8 @@ enum N2VFlag { static bool DisassembleNVdVmOptImm(MCInst &MI, unsigned Opc, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, N2VFlag Flag, BO B) { - const TargetInstrDesc &TID = ARMInsts[Opc]; - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opc]; + const MCOperandInfo *OpInfo = MCID.OpInfo; assert(NumOps >= 2 && (OpInfo[0].RegClass == ARM::DPRRegClassID || @@ -2878,7 +2878,7 @@ static bool DisassembleNVdVmOptImm(MCInst &MI, unsigned Opc, uint32_t insn, ++OpIdx; // VPADAL... - if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) { + if (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1) { // TIED_TO operand. MI.addOperand(MCOperand::CreateReg(0)); ++OpIdx; @@ -2892,7 +2892,7 @@ static bool DisassembleNVdVmOptImm(MCInst &MI, unsigned Opc, uint32_t insn, // VZIP and others have two TIED_TO reg operands. int Idx; while (OpIdx < NumOps && - (Idx = TID.getOperandConstraint(OpIdx, TOI::TIED_TO)) != -1) { + (Idx = MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO)) != -1) { // Add TIED_TO operand. MI.addOperand(MI.getOperand(Idx)); ++OpIdx; @@ -2945,8 +2945,8 @@ static bool DisassembleNVecDupLnFrm(MCInst &MI, unsigned Opc, uint32_t insn, static bool DisassembleNVectorShift(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, bool LeftShift, BO B) { - const TargetInstrDesc &TID = ARMInsts[Opcode]; - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opcode]; + const MCOperandInfo *OpInfo = MCID.OpInfo; assert(NumOps >= 3 && (OpInfo[0].RegClass == ARM::DPRRegClassID || @@ -2964,7 +2964,7 @@ static bool DisassembleNVectorShift(MCInst &MI, unsigned Opcode, uint32_t insn, decodeNEONRd(insn)))); ++OpIdx; - if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) { + if (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1) { // TIED_TO operand. MI.addOperand(MCOperand::CreateReg(0)); ++OpIdx; @@ -3044,8 +3044,8 @@ enum N3VFlag { static bool DisassembleNVdVnVmOptImm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, N3VFlag Flag, BO B) { - const TargetInstrDesc &TID = ARMInsts[Opcode]; - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opcode]; + const MCOperandInfo *OpInfo = MCID.OpInfo; // No checking for OpInfo[2] because of MOVDneon/MOVQ with only two regs. assert(NumOps >= 3 && @@ -3076,7 +3076,7 @@ static bool DisassembleNVdVnVmOptImm(MCInst &MI, unsigned Opcode, uint32_t insn, ++OpIdx; // VABA, VABAL, VBSLd, VBSLq, ... - if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) { + if (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1) { // TIED_TO operand. MI.addOperand(MCOperand::CreateReg(0)); ++OpIdx; @@ -3163,8 +3163,8 @@ static bool DisassembleNVecMulScalarFrm(MCInst &MI, unsigned Opcode, static bool DisassembleNVTBLFrm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetInstrDesc &TID = ARMInsts[Opcode]; - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opcode]; + const MCOperandInfo *OpInfo = MCID.OpInfo; if (!OpInfo) return false; assert(NumOps >= 3 && @@ -3192,7 +3192,7 @@ static bool DisassembleNVTBLFrm(MCInst &MI, unsigned Opcode, uint32_t insn, // Process tied_to operand constraint. int Idx; - if ((Idx = TID.getOperandConstraint(OpIdx, TOI::TIED_TO)) != -1) { + if ((Idx = MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO)) != -1) { MI.addOperand(MI.getOperand(Idx)); ++OpIdx; } @@ -3221,11 +3221,11 @@ static bool DisassembleNVTBLFrm(MCInst &MI, unsigned Opcode, uint32_t insn, static bool DisassembleNGetLnFrm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetInstrDesc &TID = ARMInsts[Opcode]; - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opcode]; + const MCOperandInfo *OpInfo = MCID.OpInfo; if (!OpInfo) return false; - assert(TID.getNumDefs() == 1 && NumOps >= 3 && + assert(MCID.getNumDefs() == 1 && NumOps >= 3 && OpInfo[0].RegClass == ARM::GPRRegClassID && OpInfo[1].RegClass == ARM::DPRRegClassID && OpInfo[2].RegClass < 0 && @@ -3255,14 +3255,14 @@ static bool DisassembleNGetLnFrm(MCInst &MI, unsigned Opcode, uint32_t insn, static bool DisassembleNSetLnFrm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetInstrDesc &TID = ARMInsts[Opcode]; - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opcode]; + const MCOperandInfo *OpInfo = MCID.OpInfo; if (!OpInfo) return false; - assert(TID.getNumDefs() == 1 && NumOps >= 3 && + assert(MCID.getNumDefs() == 1 && NumOps >= 3 && OpInfo[0].RegClass == ARM::DPRRegClassID && OpInfo[1].RegClass == ARM::DPRRegClassID && - TID.getOperandConstraint(1, TOI::TIED_TO) != -1 && + MCID.getOperandConstraint(1, MCOI::TIED_TO) != -1 && OpInfo[2].RegClass == ARM::GPRRegClassID && OpInfo[3].RegClass < 0 && "Expect >= 3 operands with one dst operand"); @@ -3294,7 +3294,7 @@ static bool DisassembleNSetLnFrm(MCInst &MI, unsigned Opcode, uint32_t insn, static bool DisassembleNDupFrm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; assert(NumOps >= 2 && (OpInfo[0].RegClass == ARM::DPRRegClassID || @@ -3604,11 +3604,11 @@ bool ARMBasicMCBuilder::DoPredicateOperands(MCInst& MI, unsigned Opcode, assert(NumOpsRemaining > 0 && "Invalid argument"); - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; unsigned Idx = MI.getNumOperands(); // First, we check whether this instr specifies the PredicateOperand through - // a pair of TargetOperandInfos with isPredicate() property. + // a pair of MCOperandInfos with isPredicate() property. if (NumOpsRemaining >= 2 && OpInfo[Idx].isPredicate() && OpInfo[Idx+1].isPredicate() && OpInfo[Idx].RegClass < 0 && @@ -3636,13 +3636,13 @@ bool ARMBasicMCBuilder::TryPredicateAndSBitModifier(MCInst& MI, unsigned Opcode, assert(NumOpsRemaining > 0 && "Invalid argument"); - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; const std::string &Name = ARMInsts[Opcode].Name; unsigned Idx = MI.getNumOperands(); uint64_t TSFlags = ARMInsts[Opcode].TSFlags; // First, we check whether this instr specifies the PredicateOperand through - // a pair of TargetOperandInfos with isPredicate() property. + // a pair of MCOperandInfos with isPredicate() property. if (NumOpsRemaining >= 2 && OpInfo[Idx].isPredicate() && OpInfo[Idx+1].isPredicate() && OpInfo[Idx].RegClass < 0 && diff --git a/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h b/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h index 9639c8a..834c6f6 100644 --- a/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h +++ b/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h @@ -350,7 +350,7 @@ static inline unsigned decodeRotate(uint32_t insn) { static bool DisassembleThumb1General(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; unsigned &OpIdx = NumOpsAdded; OpIdx = 0; @@ -425,8 +425,8 @@ static bool DisassembleThumb1General(MCInst &MI, unsigned Opcode, uint32_t insn, static bool DisassembleThumb1DP(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetInstrDesc &TID = ARMInsts[Opcode]; - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opcode]; + const MCOperandInfo *OpInfo = MCID.OpInfo; unsigned &OpIdx = NumOpsAdded; OpIdx = 0; @@ -454,7 +454,7 @@ static bool DisassembleThumb1DP(MCInst &MI, unsigned Opcode, uint32_t insn, assert(OpIdx < NumOps && OpInfo[OpIdx].RegClass == ARM::tGPRRegClassID && "Thumb reg operand expected"); int Idx; - if ((Idx = TID.getOperandConstraint(OpIdx, TOI::TIED_TO)) != -1) { + if ((Idx = MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO)) != -1) { // The reg operand is tied to the first reg operand. MI.addOperand(MI.getOperand(Idx)); ++OpIdx; @@ -511,8 +511,8 @@ static bool DisassembleThumb1Special(MCInst &MI, unsigned Opcode, uint32_t insn, return true; } - const TargetInstrDesc &TID = ARMInsts[Opcode]; - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opcode]; + const MCOperandInfo *OpInfo = MCID.OpInfo; unsigned &OpIdx = NumOpsAdded; OpIdx = 0; @@ -530,7 +530,7 @@ static bool DisassembleThumb1Special(MCInst &MI, unsigned Opcode, uint32_t insn, assert(OpIdx < NumOps && "More operands expected"); int Idx; - if ((Idx = TID.getOperandConstraint(OpIdx, TOI::TIED_TO)) != -1) { + if ((Idx = MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO)) != -1) { // The reg operand is tied to the first reg operand. MI.addOperand(MI.getOperand(Idx)); ++OpIdx; @@ -554,7 +554,7 @@ static bool DisassembleThumb1Special(MCInst &MI, unsigned Opcode, uint32_t insn, static bool DisassembleThumb1LdPC(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; if (!OpInfo) return false; assert(NumOps >= 2 && OpInfo[0].RegClass == ARM::tGPRRegClassID && @@ -602,7 +602,7 @@ static bool DisassembleThumb1LdPC(MCInst &MI, unsigned Opcode, uint32_t insn, static bool DisassembleThumb2Ldpci(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; if (!OpInfo) return false; assert(NumOps >= 2 && @@ -630,8 +630,8 @@ static bool DisassembleThumb2Ldpci(MCInst &MI, unsigned Opcode, static bool DisassembleThumb1LdSt(unsigned opA, MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetInstrDesc &TID = ARMInsts[Opcode]; - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opcode]; + const MCOperandInfo *OpInfo = MCID.OpInfo; unsigned &OpIdx = NumOpsAdded; assert(NumOps >= 2 @@ -680,7 +680,7 @@ static bool DisassembleThumb1LdStSP(MCInst &MI, unsigned Opcode, uint32_t insn, assert((Opcode == ARM::tLDRspi || Opcode == ARM::tSTRspi) && "Unexpected opcode"); - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; if (!OpInfo) return false; assert(NumOps >= 3 && @@ -708,7 +708,7 @@ static bool DisassembleThumb1AddPCi(MCInst &MI, unsigned Opcode, uint32_t insn, assert(Opcode == ARM::tADDrPCi && "Unexpected opcode"); - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; if (!OpInfo) return false; assert(NumOps >= 2 && OpInfo[0].RegClass == ARM::tGPRRegClassID && @@ -733,7 +733,7 @@ static bool DisassembleThumb1AddSPi(MCInst &MI, unsigned Opcode, uint32_t insn, assert(Opcode == ARM::tADDrSPi && "Unexpected opcode"); - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; if (!OpInfo) return false; assert(NumOps >= 3 && @@ -810,7 +810,7 @@ static bool DisassembleThumb1Misc(MCInst &MI, unsigned Opcode, uint32_t insn, if (Opcode == ARM::tPUSH || Opcode == ARM::tPOP) return DisassembleThumb1PushPop(MI, Opcode, insn, NumOps, NumOpsAdded, B); - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; // Predicate operands are handled elsewhere. if (NumOps == 2 && @@ -958,7 +958,7 @@ static bool DisassembleThumb1CondBr(MCInst &MI, unsigned Opcode, uint32_t insn, if (Opcode == ARM::tTRAP) return true; - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; if (!OpInfo) return false; assert(NumOps == 3 && OpInfo[0].RegClass < 0 && @@ -989,7 +989,7 @@ static bool DisassembleThumb1CondBr(MCInst &MI, unsigned Opcode, uint32_t insn, static bool DisassembleThumb1Br(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO) { - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; if (!OpInfo) return false; assert(NumOps == 1 && OpInfo[0].RegClass < 0 && "1 imm operand expected"); @@ -1226,7 +1226,7 @@ static bool DisassembleThumb2LdStMul(MCInst &MI, unsigned Opcode, uint32_t insn, static bool DisassembleThumb2LdStEx(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; if (!OpInfo) return false; unsigned &OpIdx = NumOpsAdded; @@ -1316,7 +1316,7 @@ static bool DisassembleThumb2LdStEx(MCInst &MI, unsigned Opcode, uint32_t insn, static bool DisassembleThumb2LdStDual(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; if (!OpInfo) return false; assert(NumOps >= 4 @@ -1423,8 +1423,8 @@ static inline bool Thumb2ShiftOpcode(unsigned Opcode) { static bool DisassembleThumb2DPSoReg(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetInstrDesc &TID = ARMInsts[Opcode]; - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opcode]; + const MCOperandInfo *OpInfo = MCID.OpInfo; unsigned &OpIdx = NumOpsAdded; // Special case handling. @@ -1467,7 +1467,7 @@ static bool DisassembleThumb2DPSoReg(MCInst &MI, unsigned Opcode, uint32_t insn, if (ThreeReg) { int Idx; - if ((Idx = TID.getOperandConstraint(OpIdx, TOI::TIED_TO)) != -1) { + if ((Idx = MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO)) != -1) { // Process tied_to operand constraint. MI.addOperand(MI.getOperand(Idx)); ++OpIdx; @@ -1521,8 +1521,8 @@ static bool DisassembleThumb2DPSoReg(MCInst &MI, unsigned Opcode, uint32_t insn, static bool DisassembleThumb2DPModImm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetInstrDesc &TID = ARMInsts[Opcode]; - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opcode]; + const MCOperandInfo *OpInfo = MCID.OpInfo; unsigned &OpIdx = NumOpsAdded; OpIdx = 0; @@ -1550,7 +1550,7 @@ static bool DisassembleThumb2DPModImm(MCInst &MI, unsigned Opcode, return false; } int Idx; - if ((Idx = TID.getOperandConstraint(OpIdx, TOI::TIED_TO)) != -1) { + if ((Idx = MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO)) != -1) { // The reg operand is tied to the first reg operand. MI.addOperand(MI.getOperand(Idx)); } else { @@ -1590,8 +1590,8 @@ static inline bool Thumb2SaturateOpcode(unsigned Opcode) { /// o t2SSAT16, t2USAT16: Rs sat_pos Rn static bool DisassembleThumb2Sat(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned &NumOpsAdded, BO B) { - const TargetInstrDesc &TID = ARMInsts[Opcode]; - NumOpsAdded = TID.getNumOperands() - 2; // ignore predicate operands + const MCInstrDesc &MCID = ARMInsts[Opcode]; + NumOpsAdded = MCID.getNumOperands() - 2; // ignore predicate operands // Disassemble the register def. MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::rGPRRegClassID, @@ -1635,8 +1635,8 @@ static bool DisassembleThumb2Sat(MCInst &MI, unsigned Opcode, uint32_t insn, static bool DisassembleThumb2DPBinImm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetInstrDesc &TID = ARMInsts[Opcode]; - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opcode]; + const MCOperandInfo *OpInfo = MCID.OpInfo; unsigned &OpIdx = NumOpsAdded; OpIdx = 0; @@ -1659,7 +1659,7 @@ static bool DisassembleThumb2DPBinImm(MCInst &MI, unsigned Opcode, if (TwoReg) { assert(NumOps >= 3 && "Expect >= 3 operands"); int Idx; - if ((Idx = TID.getOperandConstraint(OpIdx, TOI::TIED_TO)) != -1) { + if ((Idx = MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO)) != -1) { // Process tied_to operand constraint. MI.addOperand(MI.getOperand(Idx)); } else { @@ -1907,8 +1907,8 @@ static bool DisassembleThumb2PreLoad(MCInst &MI, unsigned Opcode, uint32_t insn, // t2PLDs: Rn Rm imm2=Inst{5-4} // Same pattern applies for t2PLDW* and t2PLI*. - const TargetInstrDesc &TID = ARMInsts[Opcode]; - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opcode]; + const MCOperandInfo *OpInfo = MCID.OpInfo; unsigned &OpIdx = NumOpsAdded; OpIdx = 0; @@ -2073,8 +2073,8 @@ static bool DisassembleThumb2LdSt(bool Load, MCInst &MI, unsigned Opcode, // See, for example, A6.3.7 Load word: Table A6-18 Load word. if (Load && Rn == 15) return DisassembleThumb2Ldpci(MI, Opcode, insn, NumOps, NumOpsAdded, B); - const TargetInstrDesc &TID = ARMInsts[Opcode]; - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opcode]; + const MCOperandInfo *OpInfo = MCID.OpInfo; unsigned &OpIdx = NumOpsAdded; OpIdx = 0; @@ -2085,7 +2085,7 @@ static bool DisassembleThumb2LdSt(bool Load, MCInst &MI, unsigned Opcode, "Expect >= 3 operands and first two as reg operands"); bool ThreeReg = (OpInfo[2].RegClass > 0); - bool TIED_TO = ThreeReg && TID.getOperandConstraint(2, TOI::TIED_TO) != -1; + bool TIED_TO = ThreeReg && MCID.getOperandConstraint(2, MCOI::TIED_TO) != -1; bool Imm12 = !ThreeReg && slice(insn, 23, 23) == 1; // ARMInstrThumb2.td // Build the register operands, followed by the immediate. @@ -2160,8 +2160,8 @@ static bool DisassembleThumb2LdSt(bool Load, MCInst &MI, unsigned Opcode, static bool DisassembleThumb2DPReg(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetInstrDesc &TID = ARMInsts[Opcode]; - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opcode]; + const MCOperandInfo *OpInfo = MCID.OpInfo; unsigned &OpIdx = NumOpsAdded; OpIdx = 0; @@ -2214,7 +2214,7 @@ static bool DisassembleThumb2DPReg(MCInst &MI, unsigned Opcode, uint32_t insn, static bool DisassembleThumb2Mul(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; assert(NumOps >= 3 && OpInfo[0].RegClass == ARM::rGPRRegClassID && @@ -2259,7 +2259,7 @@ static bool DisassembleThumb2Mul(MCInst &MI, unsigned Opcode, uint32_t insn, static bool DisassembleThumb2LongMul(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; assert(NumOps >= 3 && OpInfo[0].RegClass == ARM::rGPRRegClassID && diff --git a/lib/Target/ARM/MLxExpansionPass.cpp b/lib/Target/ARM/MLxExpansionPass.cpp index fc22861..2df0053 100644 --- a/lib/Target/ARM/MLxExpansionPass.cpp +++ b/lib/Target/ARM/MLxExpansionPass.cpp @@ -137,11 +137,11 @@ unsigned MLxExpansion::getDefReg(MachineInstr *MI) const { bool MLxExpansion::hasRAWHazard(unsigned Reg, MachineInstr *MI) const { // FIXME: Detect integer instructions properly. - const TargetInstrDesc &TID = MI->getDesc(); - unsigned Domain = TID.TSFlags & ARMII::DomainMask; - if (TID.mayStore()) + const MCInstrDesc &MCID = MI->getDesc(); + unsigned Domain = MCID.TSFlags & ARMII::DomainMask; + if (MCID.mayStore()) return false; - unsigned Opcode = TID.getOpcode(); + unsigned Opcode = MCID.getOpcode(); if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD) return false; if ((Domain & ARMII::DomainVFP) || (Domain & ARMII::DomainNEON)) @@ -218,18 +218,18 @@ MLxExpansion::ExpandFPMLxInstruction(MachineBasicBlock &MBB, MachineInstr *MI, ARMCC::CondCodes Pred = (ARMCC::CondCodes)MI->getOperand(NextOp).getImm(); unsigned PredReg = MI->getOperand(++NextOp).getReg(); - const TargetInstrDesc &TID1 = TII->get(MulOpc); - const TargetInstrDesc &TID2 = TII->get(AddSubOpc); - unsigned TmpReg = MRI->createVirtualRegister(TII->getRegClass(TID1, 0, TRI)); + const MCInstrDesc &MCID1 = TII->get(MulOpc); + const MCInstrDesc &MCID2 = TII->get(AddSubOpc); + unsigned TmpReg = MRI->createVirtualRegister(TII->getRegClass(MCID1, 0, TRI)); - MachineInstrBuilder MIB = BuildMI(MBB, *MI, MI->getDebugLoc(), TID1, TmpReg) + MachineInstrBuilder MIB = BuildMI(MBB, *MI, MI->getDebugLoc(), MCID1, TmpReg) .addReg(Src1Reg, getKillRegState(Src1Kill)) .addReg(Src2Reg, getKillRegState(Src2Kill)); if (HasLane) MIB.addImm(LaneImm); MIB.addImm(Pred).addReg(PredReg); - MIB = BuildMI(MBB, *MI, MI->getDebugLoc(), TID2) + MIB = BuildMI(MBB, *MI, MI->getDebugLoc(), MCID2) .addReg(DstReg, getDefRegState(true) | getDeadRegState(DstDead)); if (NegAcc) { @@ -273,15 +273,15 @@ bool MLxExpansion::ExpandFPMLxInstructions(MachineBasicBlock &MBB) { continue; } - const TargetInstrDesc &TID = MI->getDesc(); - if (TID.isBarrier()) { + const MCInstrDesc &MCID = MI->getDesc(); + if (MCID.isBarrier()) { clearStack(); Skip = 0; ++MII; continue; } - unsigned Domain = TID.TSFlags & ARMII::DomainMask; + unsigned Domain = MCID.TSFlags & ARMII::DomainMask; if (Domain == ARMII::DomainGeneral) { if (++Skip == 2) // Assume dual issues of non-VFP / NEON instructions. @@ -291,7 +291,7 @@ bool MLxExpansion::ExpandFPMLxInstructions(MachineBasicBlock &MBB) { unsigned MulOpc, AddSubOpc; bool NegAcc, HasLane; - if (!TII->isFpMLxInstruction(TID.getOpcode(), + if (!TII->isFpMLxInstruction(MCID.getOpcode(), MulOpc, AddSubOpc, NegAcc, HasLane) || !FindMLxHazard(MI)) pushStack(MI); diff --git a/lib/Target/ARM/Thumb1RegisterInfo.cpp b/lib/Target/ARM/Thumb1RegisterInfo.cpp index 6bf5650..2a1dbf7 100644 --- a/lib/Target/ARM/Thumb1RegisterInfo.cpp +++ b/lib/Target/ARM/Thumb1RegisterInfo.cpp @@ -239,9 +239,9 @@ void llvm::emitThumbRegPlusImmediate(MachineBasicBlock &MBB, unsigned Chunk = (1 << 3) - 1; unsigned ThisVal = (Bytes > Chunk) ? Chunk : Bytes; Bytes -= ThisVal; - const TargetInstrDesc &TID = TII.get(isSub ? ARM::tSUBi3 : ARM::tADDi3); + const MCInstrDesc &MCID = TII.get(isSub ? ARM::tSUBi3 : ARM::tADDi3); const MachineInstrBuilder MIB = - AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TID, DestReg).setMIFlags(MIFlags)); + AddDefaultT1CC(BuildMI(MBB, MBBI, dl, MCID, DestReg).setMIFlags(MIFlags)); AddDefaultPred(MIB.addReg(BaseReg, RegState::Kill).addImm(ThisVal)); } else { BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), DestReg) @@ -291,8 +291,8 @@ void llvm::emitThumbRegPlusImmediate(MachineBasicBlock &MBB, } if (ExtraOpc) { - const TargetInstrDesc &TID = TII.get(ExtraOpc); - AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TID, DestReg)) + const MCInstrDesc &MCID = TII.get(ExtraOpc); + AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, MCID, DestReg)) .addReg(DestReg, RegState::Kill) .addImm(((unsigned)NumBytes) & 3) .setMIFlags(MIFlags)); @@ -360,8 +360,8 @@ static void emitThumbConstant(MachineBasicBlock &MBB, if (Imm > 0) emitThumbRegPlusImmediate(MBB, MBBI, dl, DestReg, DestReg, Imm, TII, MRI); if (isSub) { - const TargetInstrDesc &TID = TII.get(ARM::tRSB); - AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TID, DestReg)) + const MCInstrDesc &MCID = TII.get(ARM::tRSB); + AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, MCID, DestReg)) .addReg(DestReg, RegState::Kill)); } } @@ -396,7 +396,7 @@ rewriteFrameIndex(MachineBasicBlock::iterator II, unsigned FrameRegIdx, MachineBasicBlock &MBB = *MI.getParent(); DebugLoc dl = MI.getDebugLoc(); unsigned Opcode = MI.getOpcode(); - const TargetInstrDesc &Desc = MI.getDesc(); + const MCInstrDesc &Desc = MI.getDesc(); unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask); if (Opcode == ARM::tADDrSPi) { @@ -653,7 +653,7 @@ Thumb1RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, assert(Offset && "This code isn't needed if offset already handled!"); unsigned Opcode = MI.getOpcode(); - const TargetInstrDesc &Desc = MI.getDesc(); + const MCInstrDesc &Desc = MI.getDesc(); // Remove predicate first. int PIdx = MI.findFirstPredOperandIdx(); diff --git a/lib/Target/ARM/Thumb2InstrInfo.cpp b/lib/Target/ARM/Thumb2InstrInfo.cpp index d169dbb..98151b9 100644 --- a/lib/Target/ARM/Thumb2InstrInfo.cpp +++ b/lib/Target/ARM/Thumb2InstrInfo.cpp @@ -396,7 +396,7 @@ bool llvm::rewriteT2FrameIndex(MachineInstr &MI, unsigned FrameRegIdx, unsigned FrameReg, int &Offset, const ARMBaseInstrInfo &TII) { unsigned Opcode = MI.getOpcode(); - const TargetInstrDesc &Desc = MI.getDesc(); + const MCInstrDesc &Desc = MI.getDesc(); unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask); bool isSub = false; diff --git a/lib/Target/ARM/Thumb2SizeReduction.cpp b/lib/Target/ARM/Thumb2SizeReduction.cpp index ce2e966..9b87747 100644 --- a/lib/Target/ARM/Thumb2SizeReduction.cpp +++ b/lib/Target/ARM/Thumb2SizeReduction.cpp @@ -189,8 +189,8 @@ Thumb2SizeReduce::Thumb2SizeReduce() : MachineFunctionPass(ID) { } } -static bool HasImplicitCPSRDef(const TargetInstrDesc &TID) { - for (const unsigned *Regs = TID.ImplicitDefs; *Regs; ++Regs) +static bool HasImplicitCPSRDef(const MCInstrDesc &MCID) { + for (const unsigned *Regs = MCID.ImplicitDefs; *Regs; ++Regs) if (*Regs == ARM::CPSR) return true; return false; @@ -484,8 +484,8 @@ Thumb2SizeReduce::ReduceSpecial(MachineBasicBlock &MBB, MachineInstr *MI, if (Entry.LowRegs1 && !VerifyLowRegs(MI)) return false; - const TargetInstrDesc &TID = MI->getDesc(); - if (TID.mayLoad() || TID.mayStore()) + const MCInstrDesc &MCID = MI->getDesc(); + if (MCID.mayLoad() || MCID.mayStore()) return ReduceLoadStore(MBB, MI, Entry); unsigned Opc = MI->getOpcode(); @@ -576,23 +576,23 @@ Thumb2SizeReduce::ReduceTo2Addr(MachineBasicBlock &MBB, MachineInstr *MI, } // Check if it's possible / necessary to transfer the predicate. - const TargetInstrDesc &NewTID = TII->get(Entry.NarrowOpc2); + const MCInstrDesc &NewMCID = TII->get(Entry.NarrowOpc2); unsigned PredReg = 0; ARMCC::CondCodes Pred = getInstrPredicate(MI, PredReg); bool SkipPred = false; if (Pred != ARMCC::AL) { - if (!NewTID.isPredicable()) + if (!NewMCID.isPredicable()) // Can't transfer predicate, fail. return false; } else { - SkipPred = !NewTID.isPredicable(); + SkipPred = !NewMCID.isPredicable(); } bool HasCC = false; bool CCDead = false; - const TargetInstrDesc &TID = MI->getDesc(); - if (TID.hasOptionalDef()) { - unsigned NumOps = TID.getNumOperands(); + const MCInstrDesc &MCID = MI->getDesc(); + if (MCID.hasOptionalDef()) { + unsigned NumOps = MCID.getNumOperands(); HasCC = (MI->getOperand(NumOps-1).getReg() == ARM::CPSR); if (HasCC && MI->getOperand(NumOps-1).isDead()) CCDead = true; @@ -602,15 +602,15 @@ Thumb2SizeReduce::ReduceTo2Addr(MachineBasicBlock &MBB, MachineInstr *MI, // Avoid adding a false dependency on partial flag update by some 16-bit // instructions which has the 's' bit set. - if (Entry.PartFlag && NewTID.hasOptionalDef() && HasCC && + if (Entry.PartFlag && NewMCID.hasOptionalDef() && HasCC && canAddPseudoFlagDep(CPSRDef, MI)) return false; // Add the 16-bit instruction. DebugLoc dl = MI->getDebugLoc(); - MachineInstrBuilder MIB = BuildMI(MBB, *MI, dl, NewTID); + MachineInstrBuilder MIB = BuildMI(MBB, *MI, dl, NewMCID); MIB.addOperand(MI->getOperand(0)); - if (NewTID.hasOptionalDef()) { + if (NewMCID.hasOptionalDef()) { if (HasCC) AddDefaultT1CC(MIB, CCDead); else @@ -618,11 +618,11 @@ Thumb2SizeReduce::ReduceTo2Addr(MachineBasicBlock &MBB, MachineInstr *MI, } // Transfer the rest of operands. - unsigned NumOps = TID.getNumOperands(); + unsigned NumOps = MCID.getNumOperands(); for (unsigned i = 1, e = MI->getNumOperands(); i != e; ++i) { - if (i < NumOps && TID.OpInfo[i].isOptionalDef()) + if (i < NumOps && MCID.OpInfo[i].isOptionalDef()) continue; - if (SkipPred && TID.OpInfo[i].isPredicate()) + if (SkipPred && MCID.OpInfo[i].isPredicate()) continue; MIB.addOperand(MI->getOperand(i)); } @@ -649,9 +649,9 @@ Thumb2SizeReduce::ReduceToNarrow(MachineBasicBlock &MBB, MachineInstr *MI, if (Entry.Imm1Limit) Limit = ((1 << Entry.Imm1Limit) - 1) * Scale; - const TargetInstrDesc &TID = MI->getDesc(); - for (unsigned i = 0, e = TID.getNumOperands(); i != e; ++i) { - if (TID.OpInfo[i].isPredicate()) + const MCInstrDesc &MCID = MI->getDesc(); + for (unsigned i = 0, e = MCID.getNumOperands(); i != e; ++i) { + if (MCID.OpInfo[i].isPredicate()) continue; const MachineOperand &MO = MI->getOperand(i); if (MO.isReg()) { @@ -663,29 +663,29 @@ Thumb2SizeReduce::ReduceToNarrow(MachineBasicBlock &MBB, MachineInstr *MI, if (Entry.LowRegs1 && !isARMLowRegister(Reg)) return false; } else if (MO.isImm() && - !TID.OpInfo[i].isPredicate()) { + !MCID.OpInfo[i].isPredicate()) { if (((unsigned)MO.getImm()) > Limit || (MO.getImm() & (Scale-1)) != 0) return false; } } // Check if it's possible / necessary to transfer the predicate. - const TargetInstrDesc &NewTID = TII->get(Entry.NarrowOpc1); + const MCInstrDesc &NewMCID = TII->get(Entry.NarrowOpc1); unsigned PredReg = 0; ARMCC::CondCodes Pred = getInstrPredicate(MI, PredReg); bool SkipPred = false; if (Pred != ARMCC::AL) { - if (!NewTID.isPredicable()) + if (!NewMCID.isPredicable()) // Can't transfer predicate, fail. return false; } else { - SkipPred = !NewTID.isPredicable(); + SkipPred = !NewMCID.isPredicable(); } bool HasCC = false; bool CCDead = false; - if (TID.hasOptionalDef()) { - unsigned NumOps = TID.getNumOperands(); + if (MCID.hasOptionalDef()) { + unsigned NumOps = MCID.getNumOperands(); HasCC = (MI->getOperand(NumOps-1).getReg() == ARM::CPSR); if (HasCC && MI->getOperand(NumOps-1).isDead()) CCDead = true; @@ -695,15 +695,15 @@ Thumb2SizeReduce::ReduceToNarrow(MachineBasicBlock &MBB, MachineInstr *MI, // Avoid adding a false dependency on partial flag update by some 16-bit // instructions which has the 's' bit set. - if (Entry.PartFlag && NewTID.hasOptionalDef() && HasCC && + if (Entry.PartFlag && NewMCID.hasOptionalDef() && HasCC && canAddPseudoFlagDep(CPSRDef, MI)) return false; // Add the 16-bit instruction. DebugLoc dl = MI->getDebugLoc(); - MachineInstrBuilder MIB = BuildMI(MBB, *MI, dl, NewTID); + MachineInstrBuilder MIB = BuildMI(MBB, *MI, dl, NewMCID); MIB.addOperand(MI->getOperand(0)); - if (NewTID.hasOptionalDef()) { + if (NewMCID.hasOptionalDef()) { if (HasCC) AddDefaultT1CC(MIB, CCDead); else @@ -711,15 +711,15 @@ Thumb2SizeReduce::ReduceToNarrow(MachineBasicBlock &MBB, MachineInstr *MI, } // Transfer the rest of operands. - unsigned NumOps = TID.getNumOperands(); + unsigned NumOps = MCID.getNumOperands(); for (unsigned i = 1, e = MI->getNumOperands(); i != e; ++i) { - if (i < NumOps && TID.OpInfo[i].isOptionalDef()) + if (i < NumOps && MCID.OpInfo[i].isOptionalDef()) continue; - if ((TID.getOpcode() == ARM::t2RSBSri || - TID.getOpcode() == ARM::t2RSBri) && i == 2) + if ((MCID.getOpcode() == ARM::t2RSBSri || + MCID.getOpcode() == ARM::t2RSBri) && i == 2) // Skip the zero immediate operand, it's now implicit. continue; - bool isPred = (i < NumOps && TID.OpInfo[i].isPredicate()); + bool isPred = (i < NumOps && MCID.OpInfo[i].isPredicate()); if (SkipPred && isPred) continue; const MachineOperand &MO = MI->getOperand(i); @@ -733,7 +733,7 @@ Thumb2SizeReduce::ReduceToNarrow(MachineBasicBlock &MBB, MachineInstr *MI, MIB.addOperand(MO); } } - if (!TID.isPredicable() && NewTID.isPredicable()) + if (!MCID.isPredicable() && NewMCID.isPredicable()) AddDefaultPred(MIB); // Transfer MI flags. diff --git a/lib/Target/Blackfin/BlackfinISelDAGToDAG.cpp b/lib/Target/Blackfin/BlackfinISelDAGToDAG.cpp index d587a2f..215ca43 100644 --- a/lib/Target/Blackfin/BlackfinISelDAGToDAG.cpp +++ b/lib/Target/Blackfin/BlackfinISelDAGToDAG.cpp @@ -146,21 +146,21 @@ void BlackfinDAGToDAGISel::FixRegisterClasses(SelectionDAG &DAG) { NI != DAG.allnodes_end(); ++NI) { if (NI->use_empty() || !NI->isMachineOpcode()) continue; - const TargetInstrDesc &DefTID = TII.get(NI->getMachineOpcode()); + const MCInstrDesc &DefMCID = TII.get(NI->getMachineOpcode()); for (SDNode::use_iterator UI = NI->use_begin(); !UI.atEnd(); ++UI) { if (!UI->isMachineOpcode()) continue; - if (UI.getUse().getResNo() >= DefTID.getNumDefs()) + if (UI.getUse().getResNo() >= DefMCID.getNumDefs()) continue; const TargetRegisterClass *DefRC = - TII.getRegClass(DefTID, UI.getUse().getResNo(), TRI); + TII.getRegClass(DefMCID, UI.getUse().getResNo(), TRI); - const TargetInstrDesc &UseTID = TII.get(UI->getMachineOpcode()); - if (UseTID.getNumDefs()+UI.getOperandNo() >= UseTID.getNumOperands()) + const MCInstrDesc &UseMCID = TII.get(UI->getMachineOpcode()); + if (UseMCID.getNumDefs()+UI.getOperandNo() >= UseMCID.getNumOperands()) continue; const TargetRegisterClass *UseRC = - TII.getRegClass(UseTID, UseTID.getNumDefs()+UI.getOperandNo(), TRI); + TII.getRegClass(UseMCID, UseMCID.getNumDefs()+UI.getOperandNo(), TRI); if (!DefRC || !UseRC) continue; // We cannot copy CC <-> !(CC/D) diff --git a/lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp b/lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp index 973e968..c07570a 100644 --- a/lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp +++ b/lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp @@ -109,7 +109,7 @@ static bool delayHasHazard(MachineBasicBlock::iterator &candidate, // Hazard check MachineBasicBlock::iterator a = candidate; MachineBasicBlock::iterator b = slot; - TargetInstrDesc desc = candidate->getDesc(); + MCInstrDesc desc = candidate->getDesc(); // MBB layout:- // candidate := a0 = operation(a1, a2) @@ -183,7 +183,7 @@ static bool isDelayFiller(MachineBasicBlock &MBB, if (candidate == MBB.begin()) return false; - TargetInstrDesc brdesc = (--candidate)->getDesc(); + MCInstrDesc brdesc = (--candidate)->getDesc(); return (brdesc.hasDelaySlot()); } @@ -211,7 +211,7 @@ findDelayInstr(MachineBasicBlock &MBB,MachineBasicBlock::iterator slot) { break; --I; - TargetInstrDesc desc = I->getDesc(); + MCInstrDesc desc = I->getDesc(); if (desc.hasDelaySlot() || desc.isBranch() || isDelayFiller(MBB,I) || desc.isCall() || desc.isReturn() || desc.isBarrier() || hasUnknownSideEffects(I)) diff --git a/lib/Target/MBlaze/MBlazeMCCodeEmitter.cpp b/lib/Target/MBlaze/MBlazeMCCodeEmitter.cpp index 3ece1a8..c573d4a 100644 --- a/lib/Target/MBlaze/MBlazeMCCodeEmitter.cpp +++ b/lib/Target/MBlaze/MBlazeMCCodeEmitter.cpp @@ -179,7 +179,7 @@ void MBlazeMCCodeEmitter:: EncodeInstruction(const MCInst &MI, raw_ostream &OS, SmallVectorImpl &Fixups) const { unsigned Opcode = MI.getOpcode(); - const TargetInstrDesc &Desc = TII.get(Opcode); + const MCInstrDesc &Desc = TII.get(Opcode); uint64_t TSFlags = Desc.TSFlags; // Keep track of the current byte being emitted. unsigned CurByte = 0; diff --git a/lib/Target/MSP430/MSP430InstrInfo.cpp b/lib/Target/MSP430/MSP430InstrInfo.cpp index 424df13..8ea8490 100644 --- a/lib/Target/MSP430/MSP430InstrInfo.cpp +++ b/lib/Target/MSP430/MSP430InstrInfo.cpp @@ -158,13 +158,13 @@ ReverseBranchCondition(SmallVectorImpl &Cond) const { } bool MSP430InstrInfo::isUnpredicatedTerminator(const MachineInstr *MI) const { - const TargetInstrDesc &TID = MI->getDesc(); - if (!TID.isTerminator()) return false; + const MCInstrDesc &MCID = MI->getDesc(); + if (!MCID.isTerminator()) return false; // Conditional branch is a special case. - if (TID.isBranch() && !TID.isBarrier()) + if (MCID.isBranch() && !MCID.isBarrier()) return true; - if (!TID.isPredicable()) + if (!MCID.isPredicable()) return true; return !isPredicated(MI); } @@ -293,7 +293,7 @@ MSP430InstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, /// instruction may be. This returns the maximum number of bytes. /// unsigned MSP430InstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const { - const TargetInstrDesc &Desc = MI->getDesc(); + const MCInstrDesc &Desc = MI->getDesc(); switch (Desc.TSFlags & MSP430II::SizeMask) { default: diff --git a/lib/Target/Mips/MipsDelaySlotFiller.cpp b/lib/Target/Mips/MipsDelaySlotFiller.cpp index b44a0af..c3a6211 100644 --- a/lib/Target/Mips/MipsDelaySlotFiller.cpp +++ b/lib/Target/Mips/MipsDelaySlotFiller.cpp @@ -59,10 +59,10 @@ runOnMachineBasicBlock(MachineBasicBlock &MBB) { bool Changed = false; for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I) { - const TargetInstrDesc& Tid = I->getDesc(); - if (Tid.hasDelaySlot() && + const MCInstrDesc& MCid = I->getDesc(); + if (MCid.hasDelaySlot() && (TM.getSubtarget().isMips1() || - Tid.isCall() || Tid.isBranch() || Tid.isReturn())) { + MCid.isCall() || MCid.isBranch() || MCid.isReturn())) { MachineBasicBlock::iterator J = I; ++J; BuildMI(MBB, J, I->getDebugLoc(), TII->get(Mips::NOP)); diff --git a/lib/Target/Mips/MipsExpandPseudo.cpp b/lib/Target/Mips/MipsExpandPseudo.cpp index 4423f51..a622258 100644 --- a/lib/Target/Mips/MipsExpandPseudo.cpp +++ b/lib/Target/Mips/MipsExpandPseudo.cpp @@ -61,9 +61,9 @@ bool MipsExpandPseudo::runOnMachineBasicBlock(MachineBasicBlock& MBB) { bool Changed = false; for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end();) { - const TargetInstrDesc& Tid = I->getDesc(); + const MCInstrDesc& MCid = I->getDesc(); - switch(Tid.getOpcode()) { + switch(MCid.getOpcode()) { default: ++I; continue; @@ -87,7 +87,7 @@ void MipsExpandPseudo::ExpandBuildPairF64(MachineBasicBlock& MBB, MachineBasicBlock::iterator I) { unsigned DstReg = I->getOperand(0).getReg(); unsigned LoReg = I->getOperand(1).getReg(), HiReg = I->getOperand(2).getReg(); - const TargetInstrDesc& Mtc1Tdd = TII->get(Mips::MTC1); + const MCInstrDesc& Mtc1Tdd = TII->get(Mips::MTC1); DebugLoc dl = I->getDebugLoc(); const unsigned* SubReg = TM.getRegisterInfo()->getSubRegisters(DstReg); @@ -103,7 +103,7 @@ void MipsExpandPseudo::ExpandExtractElementF64(MachineBasicBlock& MBB, unsigned DstReg = I->getOperand(0).getReg(); unsigned SrcReg = I->getOperand(1).getReg(); unsigned N = I->getOperand(2).getImm(); - const TargetInstrDesc& Mfc1Tdd = TII->get(Mips::MFC1); + const MCInstrDesc& Mfc1Tdd = TII->get(Mips::MFC1); DebugLoc dl = I->getDebugLoc(); const unsigned* SubReg = TM.getRegisterInfo()->getSubRegisters(SrcReg); diff --git a/lib/Target/Mips/MipsInstrInfo.cpp b/lib/Target/Mips/MipsInstrInfo.cpp index be044fa..df5a089 100644 --- a/lib/Target/Mips/MipsInstrInfo.cpp +++ b/lib/Target/Mips/MipsInstrInfo.cpp @@ -341,8 +341,8 @@ void MipsInstrInfo::BuildCondBr(MachineBasicBlock &MBB, const SmallVectorImpl& Cond) const { unsigned Opc = Cond[0].getImm(); - const TargetInstrDesc &TID = get(Opc); - MachineInstrBuilder MIB = BuildMI(&MBB, DL, TID); + const MCInstrDesc &MCID = get(Opc); + MachineInstrBuilder MIB = BuildMI(&MBB, DL, MCID); for (unsigned i = 1; i < Cond.size(); ++i) MIB.addReg(Cond[i].getReg()); diff --git a/lib/Target/PTX/PTXInstrInfo.cpp b/lib/Target/PTX/PTXInstrInfo.cpp index 5bdac89..665685d 100644 --- a/lib/Target/PTX/PTXInstrInfo.cpp +++ b/lib/Target/PTX/PTXInstrInfo.cpp @@ -47,8 +47,8 @@ void PTXInstrInfo::copyPhysReg(MachineBasicBlock &MBB, bool KillSrc) const { for (int i = 0, e = sizeof(map)/sizeof(map[0]); i != e; ++ i) { if (map[i].cls->contains(DstReg, SrcReg)) { - const TargetInstrDesc &TID = get(map[i].opcode); - MachineInstr *MI = BuildMI(MBB, I, DL, TID, DstReg). + const MCInstrDesc &MCID = get(map[i].opcode); + MachineInstr *MI = BuildMI(MBB, I, DL, MCID, DstReg). addReg(SrcReg, getKillRegState(KillSrc)); AddDefaultPredicate(MI); return; @@ -69,8 +69,8 @@ bool PTXInstrInfo::copyRegToReg(MachineBasicBlock &MBB, for (int i = 0, e = sizeof(map)/sizeof(map[0]); i != e; ++ i) if (DstRC == map[i].cls) { - const TargetInstrDesc &TID = get(map[i].opcode); - MachineInstr *MI = BuildMI(MBB, I, DL, TID, DstReg).addReg(SrcReg); + const MCInstrDesc &MCID = get(map[i].opcode); + MachineInstr *MI = BuildMI(MBB, I, DL, MCID, DstReg).addReg(SrcReg); AddDefaultPredicate(MI); return true; } @@ -178,13 +178,13 @@ AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock::const_iterator iter = MBB.end(); const MachineInstr& instLast1 = *--iter; - const TargetInstrDesc &desc1 = instLast1.getDesc(); + const MCInstrDesc &desc1 = instLast1.getDesc(); // for special case that MBB has only 1 instruction const bool IsSizeOne = MBB.size() == 1; // if IsSizeOne is true, *--iter and instLast2 are invalid // we put a dummy value in instLast2 and desc2 since they are used const MachineInstr& instLast2 = IsSizeOne ? instLast1 : *--iter; - const TargetInstrDesc &desc2 = IsSizeOne ? desc1 : instLast2.getDesc(); + const MCInstrDesc &desc2 = IsSizeOne ? desc1 : instLast2.getDesc(); DEBUG(dbgs() << "\n"); DEBUG(dbgs() << "AnalyzeBranch: opcode: " << instLast1.getOpcode() << "\n"); @@ -387,7 +387,7 @@ void PTXInstrInfo::AddDefaultPredicate(MachineInstr *MI) { } bool PTXInstrInfo::IsAnyKindOfBranch(const MachineInstr& inst) { - const TargetInstrDesc &desc = inst.getDesc(); + const MCInstrDesc &desc = inst.getDesc(); return desc.isTerminator() || desc.isBranch() || desc.isIndirectBranch(); } diff --git a/lib/Target/PowerPC/PPCHazardRecognizers.cpp b/lib/Target/PowerPC/PPCHazardRecognizers.cpp index 74ecff5..cddc9d8 100644 --- a/lib/Target/PowerPC/PPCHazardRecognizers.cpp +++ b/lib/Target/PowerPC/PPCHazardRecognizers.cpp @@ -73,12 +73,12 @@ PPCHazardRecognizer970::GetInstrType(unsigned Opcode, } Opcode = ~Opcode; - const TargetInstrDesc &TID = TII.get(Opcode); + const MCInstrDesc &MCID = TII.get(Opcode); - isLoad = TID.mayLoad(); - isStore = TID.mayStore(); + isLoad = MCID.mayLoad(); + isStore = MCID.mayStore(); - uint64_t TSFlags = TID.TSFlags; + uint64_t TSFlags = MCID.TSFlags; isFirst = TSFlags & PPCII::PPC970_First; isSingle = TSFlags & PPCII::PPC970_Single; diff --git a/lib/Target/PowerPC/PPCInstrInfo.cpp b/lib/Target/PowerPC/PPCInstrInfo.cpp index 53b0491..c3fbc8b 100644 --- a/lib/Target/PowerPC/PPCInstrInfo.cpp +++ b/lib/Target/PowerPC/PPCInstrInfo.cpp @@ -120,7 +120,7 @@ PPCInstrInfo::commuteInstruction(MachineInstr *MI, bool NewMI) const { // destination register as well. if (Reg0 == Reg1) { // Must be two address instruction! - assert(MI->getDesc().getOperandConstraint(0, TOI::TIED_TO) && + assert(MI->getDesc().getOperandConstraint(0, MCOI::TIED_TO) && "Expecting a two-address instruction!"); Reg2IsKill = false; ChangeReg0 = true; @@ -315,12 +315,12 @@ void PPCInstrInfo::copyPhysReg(MachineBasicBlock &MBB, else llvm_unreachable("Impossible reg-to-reg copy"); - const TargetInstrDesc &TID = get(Opc); - if (TID.getNumOperands() == 3) - BuildMI(MBB, I, DL, TID, DestReg) + const MCInstrDesc &MCID = get(Opc); + if (MCID.getNumOperands() == 3) + BuildMI(MBB, I, DL, MCID, DestReg) .addReg(SrcReg).addReg(SrcReg, getKillRegState(KillSrc)); else - BuildMI(MBB, I, DL, TID, DestReg).addReg(SrcReg, getKillRegState(KillSrc)); + BuildMI(MBB, I, DL, MCID, DestReg).addReg(SrcReg, getKillRegState(KillSrc)); } bool diff --git a/lib/Target/Sparc/DelaySlotFiller.cpp b/lib/Target/Sparc/DelaySlotFiller.cpp index 4b12852..dab35e5 100644 --- a/lib/Target/Sparc/DelaySlotFiller.cpp +++ b/lib/Target/Sparc/DelaySlotFiller.cpp @@ -298,7 +298,7 @@ bool Filler::isDelayFiller(MachineBasicBlock &MBB, return false; if (candidate->getOpcode() == SP::UNIMP) return true; - const TargetInstrDesc &prevdesc = (--candidate)->getDesc(); + const MCInstrDesc &prevdesc = (--candidate)->getDesc(); return prevdesc.hasDelaySlot(); } diff --git a/lib/Target/SystemZ/SystemZInstrBuilder.h b/lib/Target/SystemZ/SystemZInstrBuilder.h index 2f2ef08..ab45ec5 100644 --- a/lib/Target/SystemZ/SystemZInstrBuilder.h +++ b/lib/Target/SystemZ/SystemZInstrBuilder.h @@ -108,11 +108,11 @@ addFrameReference(const MachineInstrBuilder &MIB, int FI, int Offset = 0) { MachineInstr *MI = MIB; MachineFunction &MF = *MI->getParent()->getParent(); MachineFrameInfo &MFI = *MF.getFrameInfo(); - const TargetInstrDesc &TID = MI->getDesc(); + const MCInstrDesc &MCID = MI->getDesc(); unsigned Flags = 0; - if (TID.mayLoad()) + if (MCID.mayLoad()) Flags |= MachineMemOperand::MOLoad; - if (TID.mayStore()) + if (MCID.mayStore()) Flags |= MachineMemOperand::MOStore; MachineMemOperand *MMO = MF.getMachineMemOperand(MachinePointerInfo( diff --git a/lib/Target/SystemZ/SystemZInstrInfo.cpp b/lib/Target/SystemZ/SystemZInstrInfo.cpp index be52803..9488def 100644 --- a/lib/Target/SystemZ/SystemZInstrInfo.cpp +++ b/lib/Target/SystemZ/SystemZInstrInfo.cpp @@ -199,13 +199,13 @@ ReverseBranchCondition(SmallVectorImpl &Cond) const { } bool SystemZInstrInfo::isUnpredicatedTerminator(const MachineInstr *MI) const { - const TargetInstrDesc &TID = MI->getDesc(); - if (!TID.isTerminator()) return false; + const MCInstrDesc &MCID = MI->getDesc(); + if (!MCID.isTerminator()) return false; // Conditional branch is a special case. - if (TID.isBranch() && !TID.isBarrier()) + if (MCID.isBranch() && !MCID.isBarrier()) return true; - if (!TID.isPredicable()) + if (!MCID.isPredicable()) return true; return !isPredicated(MI); } @@ -343,7 +343,7 @@ SystemZInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, return Count; } -const TargetInstrDesc& +const MCInstrDesc& SystemZInstrInfo::getBrCond(SystemZCC::CondCodes CC) const { switch (CC) { default: @@ -408,7 +408,7 @@ SystemZInstrInfo::getOppositeCondition(SystemZCC::CondCodes CC) const { } } -const TargetInstrDesc& +const MCInstrDesc& SystemZInstrInfo::getLongDispOpc(unsigned Opc) const { switch (Opc) { default: diff --git a/lib/Target/SystemZ/SystemZInstrInfo.h b/lib/Target/SystemZ/SystemZInstrInfo.h index 6cb7200..a39c21e 100644 --- a/lib/Target/SystemZ/SystemZInstrInfo.h +++ b/lib/Target/SystemZ/SystemZInstrInfo.h @@ -94,10 +94,10 @@ public: SystemZCC::CondCodes getOppositeCondition(SystemZCC::CondCodes CC) const; SystemZCC::CondCodes getCondFromBranchOpc(unsigned Opc) const; - const TargetInstrDesc& getBrCond(SystemZCC::CondCodes CC) const; - const TargetInstrDesc& getLongDispOpc(unsigned Opc) const; + const MCInstrDesc& getBrCond(SystemZCC::CondCodes CC) const; + const MCInstrDesc& getLongDispOpc(unsigned Opc) const; - const TargetInstrDesc& getMemoryInstr(unsigned Opc, int64_t Offset = 0) const { + const MCInstrDesc& getMemoryInstr(unsigned Opc, int64_t Offset = 0) const { if (Offset < 0 || Offset >= 4096) return getLongDispOpc(Opc); else diff --git a/lib/Target/TargetInstrInfo.cpp b/lib/Target/TargetInstrInfo.cpp index 2cb89f4..66f8f60 100644 --- a/lib/Target/TargetInstrInfo.cpp +++ b/lib/Target/TargetInstrInfo.cpp @@ -24,22 +24,21 @@ using namespace llvm; // TargetInstrInfo //===----------------------------------------------------------------------===// -TargetInstrInfo::TargetInstrInfo(const TargetInstrDesc* Desc, - unsigned numOpcodes) - : Descriptors(Desc), NumOpcodes(numOpcodes) { +TargetInstrInfo::TargetInstrInfo(const MCInstrDesc* Desc, unsigned numOpcodes) { + InitMCInstrInfo(Desc, numOpcodes); } TargetInstrInfo::~TargetInstrInfo() { } const TargetRegisterClass* -TargetInstrInfo::getRegClass(const TargetInstrDesc &TID, unsigned OpNum, +TargetInstrInfo::getRegClass(const MCInstrDesc &MCID, unsigned OpNum, const TargetRegisterInfo *TRI) const { - if (OpNum >= TID.getNumOperands()) + if (OpNum >= MCID.getNumOperands()) return 0; - short RegClass = TID.OpInfo[OpNum].RegClass; - if (TID.OpInfo[OpNum].isLookupPtrRegClass()) + short RegClass = MCID.OpInfo[OpNum].RegClass; + if (MCID.OpInfo[OpNum].isLookupPtrRegClass()) return TRI->getPointerRegClass(RegClass); // Instructions like INSERT_SUBREG do not have fixed register classes. @@ -135,13 +134,13 @@ void TargetInstrInfo::insertNoop(MachineBasicBlock &MBB, bool TargetInstrInfo::isUnpredicatedTerminator(const MachineInstr *MI) const { - const TargetInstrDesc &TID = MI->getDesc(); - if (!TID.isTerminator()) return false; + const MCInstrDesc &MCID = MI->getDesc(); + if (!MCID.isTerminator()) return false; // Conditional branch is a special case. - if (TID.isBranch() && !TID.isBarrier()) + if (MCID.isBranch() && !MCID.isBarrier()) return true; - if (!TID.isPredicable()) + if (!MCID.isPredicable()) return true; return !isPredicated(MI); } diff --git a/lib/Target/X86/X86CodeEmitter.cpp b/lib/Target/X86/X86CodeEmitter.cpp index 421e221..4b11db7 100644 --- a/lib/Target/X86/X86CodeEmitter.cpp +++ b/lib/Target/X86/X86CodeEmitter.cpp @@ -68,7 +68,7 @@ namespace { return "X86 Machine Code Emitter"; } - void emitInstruction(MachineInstr &MI, const TargetInstrDesc *Desc); + void emitInstruction(MachineInstr &MI, const MCInstrDesc *Desc); void getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); @@ -132,7 +132,7 @@ bool Emitter::runOnMachineFunction(MachineFunction &MF) { MCE.StartMachineBasicBlock(MBB); for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); I != E; ++I) { - const TargetInstrDesc &Desc = I->getDesc(); + const MCInstrDesc &Desc = I->getDesc(); emitInstruction(*I, &Desc); // MOVPC32r is basically a call plus a pop instruction. if (Desc.getOpcode() == X86::MOVPC32r) @@ -150,7 +150,7 @@ bool Emitter::runOnMachineFunction(MachineFunction &MF) { /// size, and 3) use of X86-64 extended registers. static unsigned determineREX(const MachineInstr &MI) { unsigned REX = 0; - const TargetInstrDesc &Desc = MI.getDesc(); + const MCInstrDesc &Desc = MI.getDesc(); // Pseudo instructions do not need REX prefix byte. if ((Desc.TSFlags & X86II::FormMask) == X86II::Pseudo) @@ -161,7 +161,7 @@ static unsigned determineREX(const MachineInstr &MI) { unsigned NumOps = Desc.getNumOperands(); if (NumOps) { bool isTwoAddr = NumOps > 1 && - Desc.getOperandConstraint(1, TOI::TIED_TO) != -1; + Desc.getOperandConstraint(1, MCOI::TIED_TO) != -1; // If it accesses SPL, BPL, SIL, or DIL, then it requires a 0x40 REX prefix. unsigned i = isTwoAddr ? 1 : 0; @@ -598,7 +598,7 @@ void Emitter::emitMemModRMByte(const MachineInstr &MI, template void Emitter::emitInstruction(MachineInstr &MI, - const TargetInstrDesc *Desc) { + const MCInstrDesc *Desc) { DEBUG(dbgs() << MI); // If this is a pseudo instruction, lower it. @@ -708,9 +708,9 @@ void Emitter::emitInstruction(MachineInstr &MI, // If this is a two-address instruction, skip one of the register operands. unsigned NumOps = Desc->getNumOperands(); unsigned CurOp = 0; - if (NumOps > 1 && Desc->getOperandConstraint(1, TOI::TIED_TO) != -1) + if (NumOps > 1 && Desc->getOperandConstraint(1, MCOI::TIED_TO) != -1) ++CurOp; - else if (NumOps > 2 && Desc->getOperandConstraint(NumOps-1, TOI::TIED_TO)== 0) + else if (NumOps > 2 && Desc->getOperandConstraint(NumOps-1,MCOI::TIED_TO)== 0) // Skip the last source operand that is tied_to the dest reg. e.g. LXADD32 --NumOps; diff --git a/lib/Target/X86/X86FastISel.cpp b/lib/Target/X86/X86FastISel.cpp index a4d1c67..09ce538 100644 --- a/lib/Target/X86/X86FastISel.cpp +++ b/lib/Target/X86/X86FastISel.cpp @@ -1393,7 +1393,7 @@ bool X86FastISel::X86VisitIntrinsicCall(const IntrinsicInst &I) { assert(DI->getAddress() && "Null address should be checked earlier!"); if (!X86SelectAddress(DI->getAddress(), AM)) return false; - const TargetInstrDesc &II = TII.get(TargetOpcode::DBG_VALUE); + const MCInstrDesc &II = TII.get(TargetOpcode::DBG_VALUE); // FIXME may need to add RegState::Debug to any registers produced, // although ESP/EBP should be the only ones at the moment. addFullAddress(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II), AM). diff --git a/lib/Target/X86/X86InstrBuilder.h b/lib/Target/X86/X86InstrBuilder.h index 1ea8071..0245e5c 100644 --- a/lib/Target/X86/X86InstrBuilder.h +++ b/lib/Target/X86/X86InstrBuilder.h @@ -150,11 +150,11 @@ addFrameReference(const MachineInstrBuilder &MIB, int FI, int Offset = 0) { MachineInstr *MI = MIB; MachineFunction &MF = *MI->getParent()->getParent(); MachineFrameInfo &MFI = *MF.getFrameInfo(); - const TargetInstrDesc &TID = MI->getDesc(); + const MCInstrDesc &MCID = MI->getDesc(); unsigned Flags = 0; - if (TID.mayLoad()) + if (MCID.mayLoad()) Flags |= MachineMemOperand::MOLoad; - if (TID.mayStore()) + if (MCID.mayStore()) Flags |= MachineMemOperand::MOStore; MachineMemOperand *MMO = MF.getMachineMemOperand(MachinePointerInfo::getFixedStack(FI, Offset), diff --git a/lib/Target/X86/X86InstrInfo.cpp b/lib/Target/X86/X86InstrInfo.cpp index d4c279c..f875010 100644 --- a/lib/Target/X86/X86InstrInfo.cpp +++ b/lib/Target/X86/X86InstrInfo.cpp @@ -1689,13 +1689,13 @@ X86::CondCode X86::GetOppositeBranchCondition(X86::CondCode CC) { } bool X86InstrInfo::isUnpredicatedTerminator(const MachineInstr *MI) const { - const TargetInstrDesc &TID = MI->getDesc(); - if (!TID.isTerminator()) return false; + const MCInstrDesc &MCID = MI->getDesc(); + if (!MCID.isTerminator()) return false; // Conditional branch is a special case. - if (TID.isBranch() && !TID.isBarrier()) + if (MCID.isBranch() && !MCID.isBarrier()) return true; - if (!TID.isPredicable()) + if (!MCID.isPredicable()) return true; return !isPredicated(MI); } @@ -2225,7 +2225,7 @@ X86InstrInfo::foldMemoryOperandImpl(MachineFunction &MF, bool isTwoAddrFold = false; unsigned NumOps = MI->getDesc().getNumOperands(); bool isTwoAddr = NumOps > 1 && - MI->getDesc().getOperandConstraint(1, TOI::TIED_TO) != -1; + MI->getDesc().getOperandConstraint(1, MCOI::TIED_TO) != -1; // FIXME: AsmPrinter doesn't know how to handle // X86II::MO_GOT_ABSOLUTE_ADDRESS after folding. @@ -2543,7 +2543,7 @@ bool X86InstrInfo::canFoldMemoryOperand(const MachineInstr *MI, unsigned Opc = MI->getOpcode(); unsigned NumOps = MI->getDesc().getNumOperands(); bool isTwoAddr = NumOps > 1 && - MI->getDesc().getOperandConstraint(1, TOI::TIED_TO) != -1; + MI->getDesc().getOperandConstraint(1, MCOI::TIED_TO) != -1; // Folding a memory location into the two-address part of a two-address // instruction is different than folding it other places. It requires @@ -2589,8 +2589,8 @@ bool X86InstrInfo::unfoldMemoryOperand(MachineFunction &MF, MachineInstr *MI, return false; UnfoldStore &= FoldedStore; - const TargetInstrDesc &TID = get(Opc); - const TargetRegisterClass *RC = getRegClass(TID, Index, &RI); + const MCInstrDesc &MCID = get(Opc); + const TargetRegisterClass *RC = getRegClass(MCID, Index, &RI); if (!MI->hasOneMemOperand() && RC == &X86::VR128RegClass && !TM.getSubtarget().isUnalignedMemAccessFast()) @@ -2632,7 +2632,7 @@ bool X86InstrInfo::unfoldMemoryOperand(MachineFunction &MF, MachineInstr *MI, } // Emit the data processing instruction. - MachineInstr *DataMI = MF.CreateMachineInstr(TID, MI->getDebugLoc(), true); + MachineInstr *DataMI = MF.CreateMachineInstr(MCID, MI->getDebugLoc(), true); MachineInstrBuilder MIB(DataMI); if (FoldedStore) @@ -2685,7 +2685,7 @@ bool X86InstrInfo::unfoldMemoryOperand(MachineFunction &MF, MachineInstr *MI, // Emit the store instruction. if (UnfoldStore) { - const TargetRegisterClass *DstRC = getRegClass(TID, 0, &RI); + const TargetRegisterClass *DstRC = getRegClass(MCID, 0, &RI); std::pair MMOs = MF.extractStoreMemRefs(MI->memoperands_begin(), @@ -2710,9 +2710,9 @@ X86InstrInfo::unfoldMemoryOperand(SelectionDAG &DAG, SDNode *N, unsigned Index = I->second.second & 0xf; bool FoldedLoad = I->second.second & (1 << 4); bool FoldedStore = I->second.second & (1 << 5); - const TargetInstrDesc &TID = get(Opc); - const TargetRegisterClass *RC = getRegClass(TID, Index, &RI); - unsigned NumDefs = TID.NumDefs; + const MCInstrDesc &MCID = get(Opc); + const TargetRegisterClass *RC = getRegClass(MCID, Index, &RI); + unsigned NumDefs = MCID.NumDefs; std::vector AddrOps; std::vector BeforeOps; std::vector AfterOps; @@ -2756,13 +2756,13 @@ X86InstrInfo::unfoldMemoryOperand(SelectionDAG &DAG, SDNode *N, // Emit the data processing instruction. std::vector VTs; const TargetRegisterClass *DstRC = 0; - if (TID.getNumDefs() > 0) { - DstRC = getRegClass(TID, 0, &RI); + if (MCID.getNumDefs() > 0) { + DstRC = getRegClass(MCID, 0, &RI); VTs.push_back(*DstRC->vt_begin()); } for (unsigned i = 0, e = N->getNumValues(); i != e; ++i) { EVT VT = N->getValueType(i); - if (VT != MVT::Other && i >= (unsigned)TID.getNumDefs()) + if (VT != MVT::Other && i >= (unsigned)MCID.getNumDefs()) VTs.push_back(VT); } if (Load) diff --git a/lib/Target/X86/X86MCCodeEmitter.cpp b/lib/Target/X86/X86MCCodeEmitter.cpp index 55aceba..04149e7 100644 --- a/lib/Target/X86/X86MCCodeEmitter.cpp +++ b/lib/Target/X86/X86MCCodeEmitter.cpp @@ -111,7 +111,7 @@ public: SmallVectorImpl &Fixups) const; void EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, int MemOperand, - const MCInst &MI, const TargetInstrDesc &Desc, + const MCInst &MI, const MCInstrDesc &Desc, raw_ostream &OS) const; void EmitSegmentOverridePrefix(uint64_t TSFlags, unsigned &CurByte, @@ -119,7 +119,7 @@ public: raw_ostream &OS) const; void EmitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, int MemOperand, - const MCInst &MI, const TargetInstrDesc &Desc, + const MCInst &MI, const MCInstrDesc &Desc, raw_ostream &OS) const; }; @@ -379,7 +379,7 @@ void X86MCCodeEmitter::EmitMemModRMByte(const MCInst &MI, unsigned Op, /// called VEX. void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, int MemOperand, const MCInst &MI, - const TargetInstrDesc &Desc, + const MCInstrDesc &Desc, raw_ostream &OS) const { bool HasVEX_4V = false; if ((TSFlags >> X86II::VEXShift) & X86II::VEX_4V) @@ -586,7 +586,7 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, /// REX prefix which specifies 1) 64-bit instructions, 2) non-default operand /// size, and 3) use of X86-64 extended registers. static unsigned DetermineREXPrefix(const MCInst &MI, uint64_t TSFlags, - const TargetInstrDesc &Desc) { + const MCInstrDesc &Desc) { unsigned REX = 0; if (TSFlags & X86II::REX_W) REX |= 1 << 3; // set REX.W @@ -596,7 +596,7 @@ static unsigned DetermineREXPrefix(const MCInst &MI, uint64_t TSFlags, unsigned NumOps = MI.getNumOperands(); // FIXME: MCInst should explicitize the two-addrness. bool isTwoAddr = NumOps > 1 && - Desc.getOperandConstraint(1, TOI::TIED_TO) != -1; + Desc.getOperandConstraint(1, MCOI::TIED_TO) != -1; // If it accesses SPL, BPL, SIL, or DIL, then it requires a 0x40 REX prefix. unsigned i = isTwoAddr ? 1 : 0; @@ -713,7 +713,7 @@ void X86MCCodeEmitter::EmitSegmentOverridePrefix(uint64_t TSFlags, /// Not present, it is -1. void X86MCCodeEmitter::EmitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, int MemOperand, const MCInst &MI, - const TargetInstrDesc &Desc, + const MCInstrDesc &Desc, raw_ostream &OS) const { // Emit the lock opcode prefix as needed. @@ -803,7 +803,7 @@ void X86MCCodeEmitter:: EncodeInstruction(const MCInst &MI, raw_ostream &OS, SmallVectorImpl &Fixups) const { unsigned Opcode = MI.getOpcode(); - const TargetInstrDesc &Desc = TII.get(Opcode); + const MCInstrDesc &Desc = TII.get(Opcode); uint64_t TSFlags = Desc.TSFlags; // Pseudo instructions don't get encoded. @@ -814,9 +814,9 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS, // FIXME: This should be handled during MCInst lowering. unsigned NumOps = Desc.getNumOperands(); unsigned CurOp = 0; - if (NumOps > 1 && Desc.getOperandConstraint(1, TOI::TIED_TO) != -1) + if (NumOps > 1 && Desc.getOperandConstraint(1, MCOI::TIED_TO) != -1) ++CurOp; - else if (NumOps > 2 && Desc.getOperandConstraint(NumOps-1, TOI::TIED_TO)== 0) + else if (NumOps > 2 && Desc.getOperandConstraint(NumOps-1, MCOI::TIED_TO)== 0) // Skip the last source operand that is tied_to the dest reg. e.g. LXADD32 --NumOps; diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp index 22c1004..fa2b192 100644 --- a/utils/TableGen/InstrInfoEmitter.cpp +++ b/utils/TableGen/InstrInfoEmitter.cpp @@ -94,17 +94,17 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) { // Ptr value whose register class is resolved via callback. if (OpR->isSubClassOf("PointerLikeRegClass")) - Res += "|(1<isSubClassOf("PredicateOperand")) - Res += "|(1<isSubClassOf("OptionalDefOperand")) - Res += "|(1< &NumberedInstructions = Target.getInstructionsByEnumValue(); @@ -221,31 +221,31 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, << ",\t\"" << Inst.TheDef->getName() << "\", 0"; // Emit all of the target indepedent flags... - if (Inst.isReturn) OS << "|(1<getValueAsBitsInit("TSFlags"); diff --git a/utils/TableGen/InstrInfoEmitter.h b/utils/TableGen/InstrInfoEmitter.h index 41672cc..a665d40 100644 --- a/utils/TableGen/InstrInfoEmitter.h +++ b/utils/TableGen/InstrInfoEmitter.h @@ -54,10 +54,6 @@ private: // Operand information. void EmitOperandInfo(raw_ostream &OS, OperandInfoMapTy &OperandInfoIDs); std::vector GetOperandInfo(const CodeGenInstruction &Inst); - - void DetectRegisterClassBarriers(std::vector &Defs, - const std::vector &RCs, - std::vector &Barriers); }; } // End llvm namespace -- cgit v1.1 From 22fee2dff4c43b551aefa44a96ca74fcade6bfac Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Tue, 28 Jun 2011 20:07:07 +0000 Subject: Merge XXXGenRegisterNames.inc into XXXGenRegisterInfo.inc git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134024 91177308-0d34-0410-b5e6-96231b3b80d8 --- Makefile.rules | 22 +---------- include/llvm/MC/MCInstrDesc.h | 2 +- lib/Target/ARM/ARMBaseInfo.h | 3 +- lib/Target/ARM/ARMBaseInstrInfo.cpp | 5 ++- lib/Target/ARM/ARMInstrInfo.cpp | 1 - lib/Target/ARM/CMakeLists.txt | 3 +- .../ARM/Disassembler/ARMDisassemblerCore.cpp | 1 + lib/Target/ARM/Makefile | 3 +- lib/Target/ARM/Thumb1InstrInfo.cpp | 1 - lib/Target/ARM/Thumb2InstrInfo.cpp | 1 - lib/Target/Alpha/Alpha.h | 3 +- lib/Target/Alpha/AlphaInstrInfo.cpp | 4 +- lib/Target/Alpha/CMakeLists.txt | 3 +- lib/Target/Alpha/Makefile | 3 +- lib/Target/Blackfin/Blackfin.h | 3 +- lib/Target/Blackfin/BlackfinInstrInfo.cpp | 2 + lib/Target/Blackfin/CMakeLists.txt | 3 +- lib/Target/Blackfin/Makefile | 4 +- lib/Target/CellSPU/CMakeLists.txt | 3 +- lib/Target/CellSPU/Makefile | 4 +- lib/Target/CellSPU/SPU.h | 3 +- lib/Target/CellSPU/SPUInstrInfo.cpp | 4 +- lib/Target/MBlaze/CMakeLists.txt | 3 +- .../MBlaze/Disassembler/MBlazeDisassembler.cpp | 1 + lib/Target/MBlaze/MBlaze.h | 3 +- lib/Target/MBlaze/MBlazeInstrInfo.cpp | 2 + lib/Target/MBlaze/Makefile | 4 +- lib/Target/MSP430/CMakeLists.txt | 3 +- lib/Target/MSP430/MSP430.h | 3 +- lib/Target/MSP430/MSP430InstrInfo.cpp | 4 +- lib/Target/MSP430/Makefile | 4 +- lib/Target/Mips/CMakeLists.txt | 3 +- lib/Target/Mips/Makefile | 4 +- lib/Target/Mips/Mips.h | 3 +- lib/Target/Mips/MipsInstrInfo.cpp | 2 + lib/Target/PTX/CMakeLists.txt | 3 +- lib/Target/PTX/Makefile | 1 - lib/Target/PTX/PTX.h | 3 +- lib/Target/PTX/PTXInstrInfo.cpp | 5 ++- lib/Target/PowerPC/CMakeLists.txt | 3 +- lib/Target/PowerPC/Makefile | 2 +- lib/Target/PowerPC/PPC.h | 3 +- lib/Target/PowerPC/PPCInstrInfo.cpp | 4 +- lib/Target/Sparc/CMakeLists.txt | 3 +- lib/Target/Sparc/Makefile | 4 +- lib/Target/Sparc/Sparc.h | 3 +- lib/Target/Sparc/SparcInstrInfo.cpp | 5 ++- lib/Target/SystemZ/CMakeLists.txt | 3 +- lib/Target/SystemZ/Makefile | 4 +- lib/Target/SystemZ/SystemZ.h | 3 +- lib/Target/SystemZ/SystemZInstrInfo.cpp | 5 ++- lib/Target/X86/CMakeLists.txt | 3 +- lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp | 4 +- lib/Target/X86/InstPrinter/X86InstComments.cpp | 2 +- lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp | 2 +- lib/Target/X86/MCTargetDesc/X86TargetDesc.cpp | 5 +++ lib/Target/X86/MCTargetDesc/X86TargetDesc.h | 5 +++ lib/Target/X86/Makefile | 3 +- lib/Target/X86/X86.h | 7 +--- lib/Target/X86/X86InstrInfo.cpp | 4 +- lib/Target/XCore/CMakeLists.txt | 3 +- lib/Target/XCore/Makefile | 4 +- lib/Target/XCore/XCore.h | 3 +- lib/Target/XCore/XCoreInstrInfo.cpp | 4 +- utils/TableGen/InstrInfoEmitter.cpp | 43 ++++++++++++++++++++++ utils/TableGen/InstrInfoEmitter.h | 5 ++- utils/TableGen/TableGen.cpp | 14 +++---- 67 files changed, 165 insertions(+), 120 deletions(-) diff --git a/Makefile.rules b/Makefile.rules index 2acadd8..46a3f1b 100644 --- a/Makefile.rules +++ b/Makefile.rules @@ -1720,35 +1720,15 @@ TDFiles := $(strip $(wildcard $(PROJ_SRC_DIR)/*.td) \ # All of these files depend on tblgen and the .td files. $(INCTMPFiles) : $(TBLGEN) $(TDFiles) -$(TARGET:%=$(ObjDir)/%GenRegisterNames.inc.tmp): \ -$(ObjDir)/%GenRegisterNames.inc.tmp : %.td $(ObjDir)/.dir - $(Echo) "Building $( diff --git a/lib/Target/ARM/ARMInstrInfo.cpp b/lib/Target/ARM/ARMInstrInfo.cpp index 6f48d96..adcbf18 100644 --- a/lib/Target/ARM/ARMInstrInfo.cpp +++ b/lib/Target/ARM/ARMInstrInfo.cpp @@ -14,7 +14,6 @@ #include "ARMInstrInfo.h" #include "ARM.h" #include "ARMAddressingModes.h" -#include "ARMGenInstrInfo.inc" #include "ARMMachineFunctionInfo.h" #include "llvm/ADT/STLExtras.h" #include "llvm/CodeGen/LiveVariables.h" diff --git a/lib/Target/ARM/CMakeLists.txt b/lib/Target/ARM/CMakeLists.txt index 0a0ed3c..b1d4f54 100644 --- a/lib/Target/ARM/CMakeLists.txt +++ b/lib/Target/ARM/CMakeLists.txt @@ -1,8 +1,7 @@ set(LLVM_TARGET_DEFINITIONS ARM.td) tablegen(ARMGenRegisterInfo.inc -gen-register-info) -tablegen(ARMGenInstrNames.inc -gen-instr-enums) -tablegen(ARMGenInstrInfo.inc -gen-instr-desc) +tablegen(ARMGenInstrInfo.inc -gen-instr-info) tablegen(ARMGenCodeEmitter.inc -gen-emitter) tablegen(ARMGenMCCodeEmitter.inc -gen-emitter -mc-emitter) tablegen(ARMGenAsmWriter.inc -gen-asm-writer) diff --git a/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp b/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp index 851b2d0..fe165b0 100644 --- a/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp +++ b/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp @@ -71,6 +71,7 @@ /// { ARM::CCRRegClassID, 0|(1< EnablePPC32RS; // FIXME (64-bit): See PPCRegisterInfo.cpp. extern cl::opt EnablePPC64RS; // FIXME (64-bit): See PPCRegisterInfo.cpp. diff --git a/lib/Target/Sparc/CMakeLists.txt b/lib/Target/Sparc/CMakeLists.txt index 1a5b036..f3c691f 100644 --- a/lib/Target/Sparc/CMakeLists.txt +++ b/lib/Target/Sparc/CMakeLists.txt @@ -1,8 +1,7 @@ set(LLVM_TARGET_DEFINITIONS Sparc.td) tablegen(SparcGenRegisterInfo.inc -gen-register-info) -tablegen(SparcGenInstrNames.inc -gen-instr-enums) -tablegen(SparcGenInstrInfo.inc -gen-instr-desc) +tablegen(SparcGenInstrInfo.inc -gen-instr-info) tablegen(SparcGenAsmWriter.inc -gen-asm-writer) tablegen(SparcGenDAGISel.inc -gen-dag-isel) tablegen(SparcGenSubtarget.inc -gen-subtarget) diff --git a/lib/Target/Sparc/Makefile b/lib/Target/Sparc/Makefile index 4ef1519..c8741b5 100644 --- a/lib/Target/Sparc/Makefile +++ b/lib/Target/Sparc/Makefile @@ -12,8 +12,8 @@ LIBRARYNAME = LLVMSparcCodeGen TARGET = Sparc # Make sure that tblgen is run, first thing. -BUILT_SOURCES = SparcGenRegisterInfo.inc SparcGenInstrNames.inc \ - SparcGenInstrInfo.inc SparcGenAsmWriter.inc \ +BUILT_SOURCES = SparcGenRegisterInfo.inc SparcGenInstrInfo.inc \ + SparcGenAsmWriter.inc \ SparcGenDAGISel.inc SparcGenSubtarget.inc SparcGenCallingConv.inc DIRS = TargetInfo diff --git a/lib/Target/Sparc/Sparc.h b/lib/Target/Sparc/Sparc.h index 0f03ca3..d68535b 100644 --- a/lib/Target/Sparc/Sparc.h +++ b/lib/Target/Sparc/Sparc.h @@ -41,7 +41,8 @@ namespace llvm { // Defines symbolic names for the Sparc instructions. // -#include "SparcGenInstrNames.inc" +#define GET_INSTRINFO_ENUM +#include "SparcGenInstrInfo.inc" namespace llvm { diff --git a/lib/Target/Sparc/SparcInstrInfo.cpp b/lib/Target/Sparc/SparcInstrInfo.cpp index afa3c1f..c323af8 100644 --- a/lib/Target/Sparc/SparcInstrInfo.cpp +++ b/lib/Target/Sparc/SparcInstrInfo.cpp @@ -19,8 +19,11 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/Support/ErrorHandling.h" -#include "SparcGenInstrInfo.inc" #include "SparcMachineFunctionInfo.h" + +#define GET_INSTRINFO_MC_DESC +#include "SparcGenInstrInfo.inc" + using namespace llvm; SparcInstrInfo::SparcInstrInfo(SparcSubtarget &ST) diff --git a/lib/Target/SystemZ/CMakeLists.txt b/lib/Target/SystemZ/CMakeLists.txt index 5adf5e3..47c7a9f 100644 --- a/lib/Target/SystemZ/CMakeLists.txt +++ b/lib/Target/SystemZ/CMakeLists.txt @@ -1,8 +1,7 @@ set(LLVM_TARGET_DEFINITIONS SystemZ.td) tablegen(SystemZGenRegisterInfo.inc -gen-register-info) -tablegen(SystemZGenInstrNames.inc -gen-instr-enums) -tablegen(SystemZGenInstrInfo.inc -gen-instr-desc) +tablegen(SystemZGenInstrInfo.inc -gen-instr-info) tablegen(SystemZGenAsmWriter.inc -gen-asm-writer) tablegen(SystemZGenDAGISel.inc -gen-dag-isel) tablegen(SystemZGenCallingConv.inc -gen-callingconv) diff --git a/lib/Target/SystemZ/Makefile b/lib/Target/SystemZ/Makefile index 4b45615..682f343 100644 --- a/lib/Target/SystemZ/Makefile +++ b/lib/Target/SystemZ/Makefile @@ -12,8 +12,8 @@ LIBRARYNAME = LLVMSystemZCodeGen TARGET = SystemZ # Make sure that tblgen is run, first thing. -BUILT_SOURCES = SystemZGenRegisterInfo.inc SystemZGenInstrNames.inc \ - SystemZGenInstrInfo.inc SystemZGenAsmWriter.inc \ +BUILT_SOURCES = SystemZGenRegisterInfo.inc SystemZGenInstrInfo.inc \ + SystemZGenAsmWriter.inc \ SystemZGenDAGISel.inc SystemZGenSubtarget.inc SystemZGenCallingConv.inc DIRS = TargetInfo diff --git a/lib/Target/SystemZ/SystemZ.h b/lib/Target/SystemZ/SystemZ.h index 8bf9fc5..84d83c0 100644 --- a/lib/Target/SystemZ/SystemZ.h +++ b/lib/Target/SystemZ/SystemZ.h @@ -57,6 +57,7 @@ namespace llvm { #include "SystemZGenRegisterInfo.inc" // Defines symbolic names for the SystemZ instructions. -#include "SystemZGenInstrNames.inc" +#define GET_INSTRINFO_ENUM +#include "SystemZGenInstrInfo.inc" #endif diff --git a/lib/Target/SystemZ/SystemZInstrInfo.cpp b/lib/Target/SystemZ/SystemZInstrInfo.cpp index 9488def..b70e075 100644 --- a/lib/Target/SystemZ/SystemZInstrInfo.cpp +++ b/lib/Target/SystemZ/SystemZInstrInfo.cpp @@ -16,13 +16,16 @@ #include "SystemZInstrInfo.h" #include "SystemZMachineFunctionInfo.h" #include "SystemZTargetMachine.h" -#include "SystemZGenInstrInfo.inc" #include "llvm/Function.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/PseudoSourceValue.h" #include "llvm/Support/ErrorHandling.h" + +#define GET_INSTRINFO_MC_DESC +#include "SystemZGenInstrInfo.inc" + using namespace llvm; SystemZInstrInfo::SystemZInstrInfo(SystemZTargetMachine &tm) diff --git a/lib/Target/X86/CMakeLists.txt b/lib/Target/X86/CMakeLists.txt index 31d69af..50464e8 100644 --- a/lib/Target/X86/CMakeLists.txt +++ b/lib/Target/X86/CMakeLists.txt @@ -2,8 +2,7 @@ set(LLVM_TARGET_DEFINITIONS X86.td) tablegen(X86GenRegisterInfo.inc -gen-register-info) tablegen(X86GenDisassemblerTables.inc -gen-disassembler) -tablegen(X86GenInstrNames.inc -gen-instr-enums) -tablegen(X86GenInstrInfo.inc -gen-instr-desc) +tablegen(X86GenInstrInfo.inc -gen-instr-info) tablegen(X86GenAsmWriter.inc -gen-asm-writer) tablegen(X86GenAsmWriter1.inc -gen-asm-writer -asmwriternum=1) tablegen(X86GenAsmMatcher.inc -gen-asm-matcher) diff --git a/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp b/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp index d01a600..53738b1 100644 --- a/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp +++ b/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp @@ -16,19 +16,17 @@ #include "X86ATTInstPrinter.h" #include "X86InstComments.h" #include "X86Subtarget.h" +#include "MCTargetDesc/X86TargetDesc.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCExpr.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" #include "llvm/Support/FormattedStream.h" -#include "X86GenInstrNames.inc" #include using namespace llvm; // Include the auto-generated portion of the assembly writer. -#define GET_REGINFO_ENUM -#include "X86GenRegisterInfo.inc" #define GET_INSTRUCTION_NAME #define PRINT_ALIAS_INSTR #include "X86GenAsmWriter.inc" diff --git a/lib/Target/X86/InstPrinter/X86InstComments.cpp b/lib/Target/X86/InstPrinter/X86InstComments.cpp index c642acc..5461c83 100644 --- a/lib/Target/X86/InstPrinter/X86InstComments.cpp +++ b/lib/Target/X86/InstPrinter/X86InstComments.cpp @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// #include "X86InstComments.h" -#include "X86GenInstrNames.inc" +#include "MCTargetDesc/X86TargetDesc.h" #include "llvm/MC/MCInst.h" #include "llvm/Support/raw_ostream.h" #include "../Utils/X86ShuffleDecode.h" diff --git a/lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp b/lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp index 5f581ba..411d832 100644 --- a/lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp +++ b/lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp @@ -16,12 +16,12 @@ #include "X86IntelInstPrinter.h" #include "X86InstComments.h" #include "X86Subtarget.h" +#include "MCTargetDesc/X86TargetDesc.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCExpr.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" -#include "X86GenInstrNames.inc" #include using namespace llvm; diff --git a/lib/Target/X86/MCTargetDesc/X86TargetDesc.cpp b/lib/Target/X86/MCTargetDesc/X86TargetDesc.cpp index 7aa77bd..77bfbb9 100644 --- a/lib/Target/X86/MCTargetDesc/X86TargetDesc.cpp +++ b/lib/Target/X86/MCTargetDesc/X86TargetDesc.cpp @@ -12,11 +12,16 @@ //===----------------------------------------------------------------------===// #include "X86TargetDesc.h" +#include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/Target/TargetRegistry.h" #define GET_REGINFO_MC_DESC #include "X86GenRegisterInfo.inc" + +#define GET_INSTRINFO_MC_DESC +#include "X86GenInstrInfo.inc" + using namespace llvm; MCRegisterInfo *createX86MCRegisterInfo() { diff --git a/lib/Target/X86/MCTargetDesc/X86TargetDesc.h b/lib/Target/X86/MCTargetDesc/X86TargetDesc.h index 0d876dc..9ab622d 100644 --- a/lib/Target/X86/MCTargetDesc/X86TargetDesc.h +++ b/lib/Target/X86/MCTargetDesc/X86TargetDesc.h @@ -26,4 +26,9 @@ extern Target TheX86_32Target, TheX86_64Target; #define GET_REGINFO_ENUM #include "X86GenRegisterInfo.inc" +// Defines symbolic names for the X86 instructions. +// +#define GET_INSTRINFO_ENUM +#include "X86GenInstrInfo.inc" + #endif diff --git a/lib/Target/X86/Makefile b/lib/Target/X86/Makefile index fad8343..25da367 100644 --- a/lib/Target/X86/Makefile +++ b/lib/Target/X86/Makefile @@ -12,8 +12,7 @@ LIBRARYNAME = LLVMX86CodeGen TARGET = X86 # Make sure that tblgen is run, first thing. -BUILT_SOURCES = X86GenRegisterInfo.inc \ - X86GenInstrNames.inc X86GenInstrInfo.inc \ +BUILT_SOURCES = X86GenRegisterInfo.inc X86GenInstrInfo.inc \ X86GenAsmWriter.inc X86GenAsmMatcher.inc \ X86GenAsmWriter1.inc X86GenDAGISel.inc \ X86GenDisassemblerTables.inc X86GenFastISel.inc \ diff --git a/lib/Target/X86/X86.h b/lib/Target/X86/X86.h index 896bf0a..9d66c2f 100644 --- a/lib/Target/X86/X86.h +++ b/lib/Target/X86/X86.h @@ -15,6 +15,7 @@ #ifndef TARGET_X86_H #define TARGET_X86_H +#include "MCTargetDesc/X86TargetDesc.h" #include "llvm/Support/DataTypes.h" #include "llvm/Target/TargetMachine.h" @@ -86,10 +87,4 @@ MCObjectWriter *createX86MachObjectWriter(raw_ostream &OS, } // End llvm namespace -#include "MCTargetDesc/X86TargetDesc.h" - -// Defines symbolic names for the X86 instructions. -// -#include "X86GenInstrNames.inc" - #endif diff --git a/lib/Target/X86/X86InstrInfo.cpp b/lib/Target/X86/X86InstrInfo.cpp index f875010..3112dc7 100644 --- a/lib/Target/X86/X86InstrInfo.cpp +++ b/lib/Target/X86/X86InstrInfo.cpp @@ -13,7 +13,6 @@ #include "X86InstrInfo.h" #include "X86.h" -#include "X86GenInstrInfo.inc" #include "X86InstrBuilder.h" #include "X86MachineFunctionInfo.h" #include "X86Subtarget.h" @@ -36,6 +35,9 @@ #include "llvm/MC/MCAsmInfo.h" #include +#define GET_INSTRINFO_MC_DESC +#include "X86GenInstrInfo.inc" + using namespace llvm; static cl::opt diff --git a/lib/Target/XCore/CMakeLists.txt b/lib/Target/XCore/CMakeLists.txt index f6e7c20..358141c 100644 --- a/lib/Target/XCore/CMakeLists.txt +++ b/lib/Target/XCore/CMakeLists.txt @@ -1,8 +1,7 @@ set(LLVM_TARGET_DEFINITIONS XCore.td) tablegen(XCoreGenRegisterInfo.inc -gen-register-info) -tablegen(XCoreGenInstrNames.inc -gen-instr-enums) -tablegen(XCoreGenInstrInfo.inc -gen-instr-desc) +tablegen(XCoreGenInstrInfo.inc -gen-instr-info) tablegen(XCoreGenAsmWriter.inc -gen-asm-writer) tablegen(XCoreGenDAGISel.inc -gen-dag-isel) tablegen(XCoreGenCallingConv.inc -gen-callingconv) diff --git a/lib/Target/XCore/Makefile b/lib/Target/XCore/Makefile index ddc85dd..ec6fb4c 100644 --- a/lib/Target/XCore/Makefile +++ b/lib/Target/XCore/Makefile @@ -12,8 +12,8 @@ LIBRARYNAME = LLVMXCoreCodeGen TARGET = XCore # Make sure that tblgen is run, first thing. -BUILT_SOURCES = XCoreGenRegisterInfo.inc XCoreGenInstrNames.inc \ - XCoreGenInstrInfo.inc XCoreGenAsmWriter.inc \ +BUILT_SOURCES = XCoreGenRegisterInfo.inc XCoreGenInstrInfo.inc \ + XCoreGenAsmWriter.inc \ XCoreGenDAGISel.inc XCoreGenCallingConv.inc \ XCoreGenSubtarget.inc diff --git a/lib/Target/XCore/XCore.h b/lib/Target/XCore/XCore.h index 69c343d..ec4ab91 100644 --- a/lib/Target/XCore/XCore.h +++ b/lib/Target/XCore/XCore.h @@ -37,6 +37,7 @@ namespace llvm { // Defines symbolic names for the XCore instructions. // -#include "XCoreGenInstrNames.inc" +#define GET_INSTRINFO_ENUM +#include "XCoreGenInstrInfo.inc" #endif diff --git a/lib/Target/XCore/XCoreInstrInfo.cpp b/lib/Target/XCore/XCoreInstrInfo.cpp index 9cb6a7d..97a1d52 100644 --- a/lib/Target/XCore/XCoreInstrInfo.cpp +++ b/lib/Target/XCore/XCoreInstrInfo.cpp @@ -18,11 +18,13 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineLocation.h" -#include "XCoreGenInstrInfo.inc" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" +#define GET_INSTRINFO_MC_DESC +#include "XCoreGenInstrInfo.inc" + namespace llvm { namespace XCore { diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp index fa2b192..2f21ea6 100644 --- a/utils/TableGen/InstrInfoEmitter.cpp +++ b/utils/TableGen/InstrInfoEmitter.cpp @@ -156,9 +156,15 @@ void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS, // run - Emit the main instruction description records for the target... void InstrInfoEmitter::run(raw_ostream &OS) { + emitEnums(OS); + GatherItinClasses(); EmitSourceFileHeader("Target Instruction Descriptors", OS); + + OS << "\n#ifdef GET_INSTRINFO_MC_DESC\n"; + OS << "#undef GET_INSTRINFO_MC_DESC\n"; + OS << "namespace llvm {\n\n"; CodeGenTarget &Target = CDP.getTargetInfo(); @@ -202,6 +208,8 @@ void InstrInfoEmitter::run(raw_ostream &OS) { OperandInfoIDs, OS); OS << "};\n"; OS << "} // End llvm namespace \n"; + + OS << "#endif // GET_INSTRINFO_MC_DESC\n\n"; } void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, @@ -283,3 +291,38 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, OS << " }, // Inst #" << Num << " = " << Inst.TheDef->getName() << "\n"; } + +// emitEnums - Print out enum values for all of the instructions. +void InstrInfoEmitter::emitEnums(raw_ostream &OS) { + EmitSourceFileHeader("Target Instruction Enum Values", OS); + + OS << "\n#ifdef GET_INSTRINFO_ENUM\n"; + OS << "#undef GET_INSTRINFO_ENUM\n"; + + OS << "namespace llvm {\n\n"; + + CodeGenTarget Target(Records); + + // We must emit the PHI opcode first... + std::string Namespace = Target.getInstNamespace(); + + if (Namespace.empty()) { + fprintf(stderr, "No instructions defined!\n"); + exit(1); + } + + const std::vector &NumberedInstructions = + Target.getInstructionsByEnumValue(); + + OS << "namespace " << Namespace << " {\n"; + OS << " enum {\n"; + for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { + OS << " " << NumberedInstructions[i]->TheDef->getName() + << "\t= " << i << ",\n"; + } + OS << " INSTRUCTION_LIST_END = " << NumberedInstructions.size() << "\n"; + OS << " };\n}\n"; + OS << "} // End llvm namespace \n"; + + OS << "#endif // GET_INSTRINFO_ENUM\n\n"; +} diff --git a/utils/TableGen/InstrInfoEmitter.h b/utils/TableGen/InstrInfoEmitter.h index a665d40..165ce42 100644 --- a/utils/TableGen/InstrInfoEmitter.h +++ b/utils/TableGen/InstrInfoEmitter.h @@ -39,8 +39,9 @@ public: void run(raw_ostream &OS); private: - typedef std::map, unsigned> OperandInfoMapTy; - + void emitEnums(raw_ostream &OS); + + typedef std::map, unsigned> OperandInfoMapTy; void emitRecord(const CodeGenInstruction &Inst, unsigned Num, Record *InstrInfo, std::map, unsigned> &EL, diff --git a/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp index 6f220c9..ce16c9a 100644 --- a/utils/TableGen/TableGen.cpp +++ b/utils/TableGen/TableGen.cpp @@ -28,7 +28,6 @@ #include "EDEmitter.h" #include "Error.h" #include "FastISelEmitter.h" -#include "InstrEnumEmitter.h" #include "InstrInfoEmitter.h" #include "IntrinsicEmitter.h" #include "LLVMCConfigurationEmitter.h" @@ -55,7 +54,9 @@ enum ActionType { PrintRecords, GenEmitter, GenRegisterInfo, - GenInstrEnums, GenInstrs, GenAsmWriter, GenAsmMatcher, + GenInstrInfo, + GenAsmWriter, + GenAsmMatcher, GenARMDecoder, GenDisassembler, GenCallingConv, @@ -95,9 +96,7 @@ namespace { "Generate machine code emitter"), clEnumValN(GenRegisterInfo, "gen-register-info", "Generate registers and register classes info"), - clEnumValN(GenInstrEnums, "gen-instr-enums", - "Generate enum values for instructions"), - clEnumValN(GenInstrs, "gen-instr-desc", + clEnumValN(GenInstrInfo, "gen-instr-info", "Generate instruction descriptions"), clEnumValN(GenCallingConv, "gen-callingconv", "Generate calling convention descriptions"), @@ -260,10 +259,7 @@ int main(int argc, char **argv) { case GenRegisterInfo: RegisterInfoEmitter(Records).run(Out.os()); break; - case GenInstrEnums: - InstrEnumEmitter(Records).run(Out.os()); - break; - case GenInstrs: + case GenInstrInfo: InstrInfoEmitter(Records).run(Out.os()); break; case GenCallingConv: -- cgit v1.1 From 94b01f688256fca49decb239a8c84b003f18cdbc Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Tue, 28 Jun 2011 20:29:03 +0000 Subject: Add MCInstrInfo registeration machinery. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134026 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Target/TargetRegistry.h | 62 +++++++++++++++++++++++++++ lib/Target/X86/MCTargetDesc/X86TargetDesc.cpp | 6 +++ utils/TableGen/InstrInfoEmitter.cpp | 10 ++++- 3 files changed, 77 insertions(+), 1 deletion(-) diff --git a/include/llvm/Target/TargetRegistry.h b/include/llvm/Target/TargetRegistry.h index cf33899..071198f 100644 --- a/include/llvm/Target/TargetRegistry.h +++ b/include/llvm/Target/TargetRegistry.h @@ -33,6 +33,7 @@ namespace llvm { class MCContext; class MCDisassembler; class MCInstPrinter; + class MCInstrInfo; class MCRegisterInfo; class MCStreamer; class TargetAsmBackend; @@ -66,6 +67,7 @@ namespace llvm { typedef MCAsmInfo *(*AsmInfoCtorFnTy)(const Target &T, StringRef TT); + typedef MCInstrInfo *(*MCInstrInfoCtorFnTy)(void); typedef MCRegisterInfo *(*MCRegInfoCtorFnTy)(void); typedef TargetMachine *(*TargetMachineCtorTy)(const Target &T, const std::string &TT, @@ -126,6 +128,10 @@ namespace llvm { /// registered. AsmInfoCtorFnTy AsmInfoCtorFn; + /// MCInstrInfoCtorFn - Constructor function for this target's MCInstrInfo, + /// if registered. + MCInstrInfoCtorFnTy MCInstrInfoCtorFn; + /// MCRegInfoCtorFn - Constructor function for this target's MCRegisterInfo, /// if registered. MCRegInfoCtorFnTy MCRegInfoCtorFn; @@ -239,6 +245,14 @@ namespace llvm { return AsmInfoCtorFn(*this, Triple); } + /// createMCInstrInfo - Create a MCInstrInfo implementation. + /// + MCInstrInfo *createMCInstrInfo() const { + if (!MCInstrInfoCtorFn) + return 0; + return MCInstrInfoCtorFn(); + } + /// createMCRegInfo - Create a MCRegisterInfo implementation. /// MCRegisterInfo *createMCRegInfo() const { @@ -460,6 +474,21 @@ namespace llvm { T.AsmInfoCtorFn = Fn; } + /// RegisterMCInstrInfo - Register a MCInstrInfo implementation for the + /// given target. + /// + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. + /// + /// @param T - The target being registered. + /// @param Fn - A function to construct a MCInstrInfo for the target. + static void RegisterMCInstrInfo(Target &T, Target::MCInstrInfoCtorFnTy Fn) { + // Ignore duplicate registration. + if (!T.MCInstrInfoCtorFn) + T.MCInstrInfoCtorFn = Fn; + } + /// RegisterMCRegInfo - Register a MCRegisterInfo implementation for the /// given target. /// @@ -685,6 +714,39 @@ namespace llvm { } }; + /// RegisterMCInstrInfo - Helper template for registering a target instruction + /// info implementation. This invokes the static "Create" method on the class + /// to actually do the construction. Usage: + /// + /// extern "C" void LLVMInitializeFooTarget() { + /// extern Target TheFooTarget; + /// RegisterMCInstrInfo X(TheFooTarget); + /// } + template + struct RegisterMCInstrInfo { + RegisterMCInstrInfo(Target &T) { + TargetRegistry::RegisterMCInstrInfo(T, &Allocator); + } + private: + static MCInstrInfo *Allocator() { + return new MCInstrInfoImpl(); + } + }; + + /// RegisterMCInstrInfoFn - Helper template for registering a target + /// instruction info implementation. This invokes the specified function to + /// do the construction. Usage: + /// + /// extern "C" void LLVMInitializeFooTarget() { + /// extern Target TheFooTarget; + /// RegisterMCInstrInfoFn X(TheFooTarget, TheFunction); + /// } + struct RegisterMCInstrInfoFn { + RegisterMCInstrInfoFn(Target &T, Target::MCInstrInfoCtorFnTy Fn) { + TargetRegistry::RegisterMCInstrInfo(T, Fn); + } + }; + /// RegisterMCRegInfo - Helper template for registering a target register info /// implementation. This invokes the static "Create" method on the class to /// actually do the construction. Usage: diff --git a/lib/Target/X86/MCTargetDesc/X86TargetDesc.cpp b/lib/Target/X86/MCTargetDesc/X86TargetDesc.cpp index 77bfbb9..44d1097 100644 --- a/lib/Target/X86/MCTargetDesc/X86TargetDesc.cpp +++ b/lib/Target/X86/MCTargetDesc/X86TargetDesc.cpp @@ -24,6 +24,12 @@ using namespace llvm; +MCInstrInfo *createX86MCInstrInfo() { + MCInstrInfo *X = new MCInstrInfo(); + InitX86MCInstrInfo(X); + return X; +} + MCRegisterInfo *createX86MCRegisterInfo() { MCRegisterInfo *X = new MCRegisterInfo(); InitX86MCRegisterInfo(X); diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp index 2f21ea6..7b90663 100644 --- a/utils/TableGen/InstrInfoEmitter.cpp +++ b/utils/TableGen/InstrInfoEmitter.cpp @@ -206,7 +206,15 @@ void InstrInfoEmitter::run(raw_ostream &OS) { for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) emitRecord(*NumberedInstructions[i], i, InstrInfo, EmittedLists, OperandInfoIDs, OS); - OS << "};\n"; + OS << "};\n\n"; + + + // MCInstrInfo initialization routine. + OS << "static inline void Init" << TargetName + << "MCInstrInfo(MCInstrInfo *II) {\n"; + OS << " II->InitMCInstrInfo(" << TargetName << "Insts, " + << NumberedInstructions.size() << ");\n}\n\n"; + OS << "} // End llvm namespace \n"; OS << "#endif // GET_INSTRINFO_MC_DESC\n\n"; -- cgit v1.1 From 6844f7bcdec8c2691c8d1067d90e4a02cf658c27 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Tue, 28 Jun 2011 20:44:22 +0000 Subject: Hide more details in tablegen generated MCRegisterInfo ctor function. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134027 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMBaseRegisterInfo.cpp | 3 +-- lib/Target/Alpha/AlphaRegisterInfo.cpp | 3 +-- lib/Target/Blackfin/BlackfinRegisterInfo.cpp | 3 +-- lib/Target/CellSPU/SPURegisterInfo.cpp | 3 +-- lib/Target/MBlaze/MBlazeRegisterInfo.cpp | 3 +-- lib/Target/MSP430/MSP430RegisterInfo.cpp | 3 +-- lib/Target/Mips/MipsRegisterInfo.cpp | 3 +-- lib/Target/PTX/PTXRegisterInfo.cpp | 2 +- lib/Target/PowerPC/PPCRegisterInfo.cpp | 3 +-- lib/Target/Sparc/SparcRegisterInfo.cpp | 3 +-- lib/Target/SystemZ/SystemZRegisterInfo.cpp | 3 +-- lib/Target/X86/X86RegisterInfo.cpp | 3 +-- lib/Target/XCore/XCoreRegisterInfo.cpp | 3 +-- utils/TableGen/RegisterInfoEmitter.cpp | 14 +++++++------- 14 files changed, 20 insertions(+), 32 deletions(-) diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/lib/Target/ARM/ARMBaseRegisterInfo.cpp index 8f10343..fa937f3 100644 --- a/lib/Target/ARM/ARMBaseRegisterInfo.cpp +++ b/lib/Target/ARM/ARMBaseRegisterInfo.cpp @@ -58,8 +58,7 @@ EnableBasePointer("arm-use-base-pointer", cl::Hidden, cl::init(true), ARMBaseRegisterInfo::ARMBaseRegisterInfo(const ARMBaseInstrInfo &tii, const ARMSubtarget &sti) - : ARMGenRegisterInfo(ARMRegDesc, ARMRegInfoDesc, - ARM::ADJCALLSTACKDOWN, ARM::ADJCALLSTACKUP), + : ARMGenRegisterInfo(ARM::ADJCALLSTACKDOWN, ARM::ADJCALLSTACKUP), TII(tii), STI(sti), FramePtr((STI.isTargetDarwin() || STI.isThumb()) ? ARM::R7 : ARM::R11), BasePtr(ARM::R6) { diff --git a/lib/Target/Alpha/AlphaRegisterInfo.cpp b/lib/Target/Alpha/AlphaRegisterInfo.cpp index 3eef05f..b0bb7c0 100644 --- a/lib/Target/Alpha/AlphaRegisterInfo.cpp +++ b/lib/Target/Alpha/AlphaRegisterInfo.cpp @@ -41,8 +41,7 @@ using namespace llvm; AlphaRegisterInfo::AlphaRegisterInfo(const TargetInstrInfo &tii) - : AlphaGenRegisterInfo(AlphaRegDesc, AlphaRegInfoDesc, - Alpha::ADJUSTSTACKDOWN, Alpha::ADJUSTSTACKUP), + : AlphaGenRegisterInfo(Alpha::ADJUSTSTACKDOWN, Alpha::ADJUSTSTACKUP), TII(tii) { } diff --git a/lib/Target/Blackfin/BlackfinRegisterInfo.cpp b/lib/Target/Blackfin/BlackfinRegisterInfo.cpp index aa43744..e0fcce0 100644 --- a/lib/Target/Blackfin/BlackfinRegisterInfo.cpp +++ b/lib/Target/Blackfin/BlackfinRegisterInfo.cpp @@ -38,8 +38,7 @@ using namespace llvm; BlackfinRegisterInfo::BlackfinRegisterInfo(BlackfinSubtarget &st, const TargetInstrInfo &tii) - : BlackfinGenRegisterInfo(BlackfinRegDesc, BlackfinRegInfoDesc, - BF::ADJCALLSTACKDOWN, BF::ADJCALLSTACKUP), + : BlackfinGenRegisterInfo(BF::ADJCALLSTACKDOWN, BF::ADJCALLSTACKUP), Subtarget(st), TII(tii) {} diff --git a/lib/Target/CellSPU/SPURegisterInfo.cpp b/lib/Target/CellSPU/SPURegisterInfo.cpp index a84dd5a..e37bc9b 100644 --- a/lib/Target/CellSPU/SPURegisterInfo.cpp +++ b/lib/Target/CellSPU/SPURegisterInfo.cpp @@ -189,8 +189,7 @@ unsigned SPURegisterInfo::getRegisterNumbering(unsigned RegEnum) { SPURegisterInfo::SPURegisterInfo(const SPUSubtarget &subtarget, const TargetInstrInfo &tii) : - SPUGenRegisterInfo(SPURegDesc, SPURegInfoDesc, - SPU::ADJCALLSTACKDOWN, SPU::ADJCALLSTACKUP), + SPUGenRegisterInfo(SPU::ADJCALLSTACKDOWN, SPU::ADJCALLSTACKUP), Subtarget(subtarget), TII(tii) { diff --git a/lib/Target/MBlaze/MBlazeRegisterInfo.cpp b/lib/Target/MBlaze/MBlazeRegisterInfo.cpp index 415c83b..c370065 100644 --- a/lib/Target/MBlaze/MBlazeRegisterInfo.cpp +++ b/lib/Target/MBlaze/MBlazeRegisterInfo.cpp @@ -45,8 +45,7 @@ using namespace llvm; MBlazeRegisterInfo:: MBlazeRegisterInfo(const MBlazeSubtarget &ST, const TargetInstrInfo &tii) - : MBlazeGenRegisterInfo(MBlazeRegDesc, MBlazeRegInfoDesc, - MBlaze::ADJCALLSTACKDOWN, MBlaze::ADJCALLSTACKUP), + : MBlazeGenRegisterInfo(MBlaze::ADJCALLSTACKDOWN, MBlaze::ADJCALLSTACKUP), Subtarget(ST), TII(tii) {} /// getRegisterNumbering - Given the enum value for some register, e.g. diff --git a/lib/Target/MSP430/MSP430RegisterInfo.cpp b/lib/Target/MSP430/MSP430RegisterInfo.cpp index 0a2e93a..eaa9947 100644 --- a/lib/Target/MSP430/MSP430RegisterInfo.cpp +++ b/lib/Target/MSP430/MSP430RegisterInfo.cpp @@ -35,8 +35,7 @@ using namespace llvm; // FIXME: Provide proper call frame setup / destroy opcodes. MSP430RegisterInfo::MSP430RegisterInfo(MSP430TargetMachine &tm, const TargetInstrInfo &tii) - : MSP430GenRegisterInfo(MSP430RegDesc, MSP430RegInfoDesc, - MSP430::ADJCALLSTACKDOWN, MSP430::ADJCALLSTACKUP), + : MSP430GenRegisterInfo(MSP430::ADJCALLSTACKDOWN, MSP430::ADJCALLSTACKUP), TM(tm), TII(tii) { StackAlign = TM.getFrameLowering()->getStackAlignment(); } diff --git a/lib/Target/Mips/MipsRegisterInfo.cpp b/lib/Target/Mips/MipsRegisterInfo.cpp index 2b74f73..1025583 100644 --- a/lib/Target/Mips/MipsRegisterInfo.cpp +++ b/lib/Target/Mips/MipsRegisterInfo.cpp @@ -44,8 +44,7 @@ using namespace llvm; MipsRegisterInfo::MipsRegisterInfo(const MipsSubtarget &ST, const TargetInstrInfo &tii) - : MipsGenRegisterInfo(MipsRegDesc, MipsRegInfoDesc, - Mips::ADJCALLSTACKDOWN, Mips::ADJCALLSTACKUP), + : MipsGenRegisterInfo(Mips::ADJCALLSTACKDOWN, Mips::ADJCALLSTACKUP), Subtarget(ST), TII(tii) {} /// getRegisterNumbering - Given the enum value for some register, e.g. diff --git a/lib/Target/PTX/PTXRegisterInfo.cpp b/lib/Target/PTX/PTXRegisterInfo.cpp index 06c5424..f32c2b7 100644 --- a/lib/Target/PTX/PTXRegisterInfo.cpp +++ b/lib/Target/PTX/PTXRegisterInfo.cpp @@ -25,7 +25,7 @@ using namespace llvm; PTXRegisterInfo::PTXRegisterInfo(PTXTargetMachine &TM, const TargetInstrInfo &TII) - : PTXGenRegisterInfo(PTXRegDesc, PTXRegInfoDesc) { + : PTXGenRegisterInfo() { } void PTXRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, diff --git a/lib/Target/PowerPC/PPCRegisterInfo.cpp b/lib/Target/PowerPC/PPCRegisterInfo.cpp index bd5c722..91408cc 100644 --- a/lib/Target/PowerPC/PPCRegisterInfo.cpp +++ b/lib/Target/PowerPC/PPCRegisterInfo.cpp @@ -114,8 +114,7 @@ unsigned PPCRegisterInfo::getRegisterNumbering(unsigned RegEnum) { PPCRegisterInfo::PPCRegisterInfo(const PPCSubtarget &ST, const TargetInstrInfo &tii) - : PPCGenRegisterInfo(PPCRegDesc, PPCRegInfoDesc, - PPC::ADJCALLSTACKDOWN, PPC::ADJCALLSTACKUP), + : PPCGenRegisterInfo(PPC::ADJCALLSTACKDOWN, PPC::ADJCALLSTACKUP), Subtarget(ST), TII(tii) { ImmToIdxMap[PPC::LD] = PPC::LDX; ImmToIdxMap[PPC::STD] = PPC::STDX; ImmToIdxMap[PPC::LBZ] = PPC::LBZX; ImmToIdxMap[PPC::STB] = PPC::STBX; diff --git a/lib/Target/Sparc/SparcRegisterInfo.cpp b/lib/Target/Sparc/SparcRegisterInfo.cpp index 48ca15b..127b951 100644 --- a/lib/Target/Sparc/SparcRegisterInfo.cpp +++ b/lib/Target/Sparc/SparcRegisterInfo.cpp @@ -32,8 +32,7 @@ using namespace llvm; SparcRegisterInfo::SparcRegisterInfo(SparcSubtarget &st, const TargetInstrInfo &tii) - : SparcGenRegisterInfo(SparcRegDesc, SparcRegInfoDesc, - SP::ADJCALLSTACKDOWN, SP::ADJCALLSTACKUP), + : SparcGenRegisterInfo(SP::ADJCALLSTACKDOWN, SP::ADJCALLSTACKUP), Subtarget(st), TII(tii) { } diff --git a/lib/Target/SystemZ/SystemZRegisterInfo.cpp b/lib/Target/SystemZ/SystemZRegisterInfo.cpp index b3c76dd..319cc46 100644 --- a/lib/Target/SystemZ/SystemZRegisterInfo.cpp +++ b/lib/Target/SystemZ/SystemZRegisterInfo.cpp @@ -34,8 +34,7 @@ using namespace llvm; SystemZRegisterInfo::SystemZRegisterInfo(SystemZTargetMachine &tm, const SystemZInstrInfo &tii) - : SystemZGenRegisterInfo(SystemZRegDesc, SystemZRegInfoDesc, - SystemZ::ADJCALLSTACKUP, SystemZ::ADJCALLSTACKDOWN), + : SystemZGenRegisterInfo(SystemZ::ADJCALLSTACKUP, SystemZ::ADJCALLSTACKDOWN), TM(tm), TII(tii) { } diff --git a/lib/Target/X86/X86RegisterInfo.cpp b/lib/Target/X86/X86RegisterInfo.cpp index 9e4fdad..d771d40 100644 --- a/lib/Target/X86/X86RegisterInfo.cpp +++ b/lib/Target/X86/X86RegisterInfo.cpp @@ -54,8 +54,7 @@ ForceStackAlign("force-align-stack", X86RegisterInfo::X86RegisterInfo(X86TargetMachine &tm, const TargetInstrInfo &tii) - : X86GenRegisterInfo(X86RegDesc, X86RegInfoDesc, - tm.getSubtarget().is64Bit() ? + : X86GenRegisterInfo(tm.getSubtarget().is64Bit() ? X86::ADJCALLSTACKDOWN64 : X86::ADJCALLSTACKDOWN32, tm.getSubtarget().is64Bit() ? diff --git a/lib/Target/XCore/XCoreRegisterInfo.cpp b/lib/Target/XCore/XCoreRegisterInfo.cpp index 0c9473e..ecb9e80 100644 --- a/lib/Target/XCore/XCoreRegisterInfo.cpp +++ b/lib/Target/XCore/XCoreRegisterInfo.cpp @@ -40,8 +40,7 @@ using namespace llvm; XCoreRegisterInfo::XCoreRegisterInfo(const TargetInstrInfo &tii) - : XCoreGenRegisterInfo(XCoreRegDesc, XCoreRegInfoDesc, - XCore::ADJCALLSTACKDOWN, XCore::ADJCALLSTACKUP), + : XCoreGenRegisterInfo(XCore::ADJCALLSTACKDOWN, XCore::ADJCALLSTACKUP), TII(tii) { } diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp index 5753c80..bf27053 100644 --- a/utils/TableGen/RegisterInfoEmitter.cpp +++ b/utils/TableGen/RegisterInfoEmitter.cpp @@ -215,8 +215,7 @@ RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target, OS << "struct " << ClassName << " : public TargetRegisterInfo {\n" << " explicit " << ClassName - << "(const MCRegisterDesc *D, const TargetRegisterInfoDesc *ID, " - << "int CallFrameSetupOpcode = -1, int CallFrameDestroyOpcode = -1);\n" + << "(int CallFrameSetupOpcode = -1, int CallFrameDestroyOpcode = -1);\n" << " virtual int getDwarfRegNumFull(unsigned RegNum, " << "unsigned Flavour) const;\n" << " virtual int getLLVMRegNumFull(unsigned DwarfRegNum, " @@ -549,8 +548,9 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, OS << " };\n"; // Emit extra information about registers. + const std::string &TargetName = Target.getName(); OS << "\n static const TargetRegisterInfoDesc " - << Target.getName() << "RegInfoDesc[] = " + << TargetName << "RegInfoDesc[] = " << "{ // Extra Descriptors\n"; OS << " { 0, 0 },\n"; @@ -660,13 +660,13 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, // Emit the constructor of the class... OS << ClassName << "::" << ClassName - << "(const MCRegisterDesc *D, const TargetRegisterInfoDesc *ID, " - << "int CallFrameSetupOpcode, int CallFrameDestroyOpcode)\n" - << " : TargetRegisterInfo(ID" + << "(int CallFrameSetupOpcode, int CallFrameDestroyOpcode)\n" + << " : TargetRegisterInfo(" << TargetName << "RegInfoDesc" << ", RegisterClasses, RegisterClasses+" << RegisterClasses.size() <<",\n" << " SubRegIndexTable,\n" << " CallFrameSetupOpcode, CallFrameDestroyOpcode) {\n" - << " InitMCRegisterInfo(D, " << Regs.size()+1 << ");\n" + << " InitMCRegisterInfo(" << TargetName << "RegDesc, " + << Regs.size()+1 << ");\n" << "}\n\n"; // Collect all information about dwarf register numbers -- cgit v1.1 From d5b03f252c0db6b49a242abab63d7c5a260fceae Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Tue, 28 Jun 2011 21:14:33 +0000 Subject: Move CallFrameSetupOpcode and CallFrameDestroyOpcode to TargetInstrInfo. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134030 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Target/TargetInstrInfo.h | 20 ++++++++++++++++++-- include/llvm/Target/TargetRegisterInfo.h | 17 +---------------- lib/CodeGen/PrologEpilogInserter.cpp | 10 ++++++---- lib/Target/ARM/ARMBaseInstrInfo.cpp | 3 ++- lib/Target/ARM/ARMBaseRegisterInfo.cpp | 3 +-- lib/Target/ARM/ARMFastISel.cpp | 4 ++-- lib/Target/Alpha/AlphaInstrInfo.cpp | 3 ++- lib/Target/Alpha/AlphaRegisterInfo.cpp | 2 +- lib/Target/Blackfin/BlackfinInstrInfo.cpp | 3 ++- lib/Target/Blackfin/BlackfinRegisterInfo.cpp | 4 +--- lib/Target/CellSPU/SPUInstrInfo.cpp | 3 ++- lib/Target/CellSPU/SPURegisterInfo.cpp | 4 +--- lib/Target/MBlaze/MBlazeInstrInfo.cpp | 3 ++- lib/Target/MBlaze/MBlazeRegisterInfo.cpp | 3 +-- lib/Target/MSP430/MSP430InstrInfo.cpp | 3 ++- lib/Target/MSP430/MSP430RegisterInfo.cpp | 9 ++++----- lib/Target/Mips/MipsInstrInfo.cpp | 3 ++- lib/Target/Mips/MipsRegisterInfo.cpp | 3 +-- lib/Target/PowerPC/PPCInstrInfo.cpp | 5 +++-- lib/Target/PowerPC/PPCRegisterInfo.cpp | 3 +-- lib/Target/Sparc/SparcInstrInfo.cpp | 3 ++- lib/Target/Sparc/SparcRegisterInfo.cpp | 3 +-- lib/Target/SystemZ/SystemZInstrInfo.cpp | 3 ++- lib/Target/SystemZ/SystemZRegisterInfo.cpp | 3 +-- lib/Target/TargetInstrInfo.cpp | 5 ++++- lib/Target/TargetRegisterInfo.cpp | 5 +---- lib/Target/X86/X86FastISel.cpp | 4 ++-- lib/Target/X86/X86InstrInfo.cpp | 8 +++++++- lib/Target/X86/X86RegisterInfo.cpp | 16 +++++----------- lib/Target/XCore/XCoreInstrInfo.cpp | 3 ++- lib/Target/XCore/XCoreRegisterInfo.cpp | 3 +-- utils/TableGen/RegisterInfoEmitter.cpp | 8 +++----- 32 files changed, 86 insertions(+), 86 deletions(-) diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h index 271f9e7..980a537 100644 --- a/include/llvm/Target/TargetInstrInfo.h +++ b/include/llvm/Target/TargetInstrInfo.h @@ -44,7 +44,9 @@ class TargetInstrInfo : public MCInstrInfo { TargetInstrInfo(const TargetInstrInfo &); // DO NOT IMPLEMENT void operator=(const TargetInstrInfo &); // DO NOT IMPLEMENT public: - TargetInstrInfo(const MCInstrDesc *desc, unsigned NumOpcodes); + TargetInstrInfo(const MCInstrDesc *desc, unsigned NumOpcodes, + int CallFrameSetupOpcode = -1, + int CallFrameDestroyOpcode = -1); virtual ~TargetInstrInfo(); /// getRegClass - Givem a machine instruction descriptor, returns the register @@ -86,6 +88,15 @@ private: AliasAnalysis *AA) const; public: + /// getCallFrameSetup/DestroyOpcode - These methods return the opcode of the + /// frame setup/destroy instructions if they exist (-1 otherwise). Some + /// targets use pseudo instructions in order to abstract away the difference + /// between operating with a frame pointer and operating without, through the + /// use of these two instructions. + /// + int getCallFrameSetupOpcode() const { return CallFrameSetupOpcode; } + int getCallFrameDestroyOpcode() const { return CallFrameDestroyOpcode; } + /// isCoalescableExtInstr - Return true if the instruction is a "coalescable" /// extension instruction. That is, it's like a copy where it's legal for the /// source to overlap the destination. e.g. X86::MOVSX64rr32. If this returns @@ -656,6 +667,9 @@ public: virtual bool hasLowDefLatency(const InstrItineraryData *ItinData, const MachineInstr *DefMI, unsigned DefIdx) const; + +private: + int CallFrameSetupOpcode, CallFrameDestroyOpcode; }; /// TargetInstrInfoImpl - This is the default implementation of @@ -664,7 +678,9 @@ public: /// libcodegen, not in libtarget. class TargetInstrInfoImpl : public TargetInstrInfo { protected: - TargetInstrInfoImpl(const MCInstrDesc *desc, unsigned NumOpcodes) + TargetInstrInfoImpl(const MCInstrDesc *desc, unsigned NumOpcodes, + int CallFrameSetupOpcode = -1, + int CallFrameDestroyOpcode = -1) : TargetInstrInfo(desc, NumOpcodes) {} public: virtual void ReplaceTailWithBranchTo(MachineBasicBlock::iterator OldInst, diff --git a/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h index 1ca7651..2965b1d 100644 --- a/include/llvm/Target/TargetRegisterInfo.h +++ b/include/llvm/Target/TargetRegisterInfo.h @@ -275,15 +275,12 @@ private: const TargetRegisterInfoDesc *InfoDesc; // Extra desc array for codegen const char *const *SubRegIndexNames; // Names of subreg indexes. regclass_iterator RegClassBegin, RegClassEnd; // List of regclasses - int CallFrameSetupOpcode, CallFrameDestroyOpcode; protected: TargetRegisterInfo(const TargetRegisterInfoDesc *ID, regclass_iterator RegClassBegin, regclass_iterator RegClassEnd, - const char *const *subregindexnames, - int CallFrameSetupOpcode = -1, - int CallFrameDestroyOpcode = -1); + const char *const *subregindexnames); virtual ~TargetRegisterInfo(); public: @@ -661,15 +658,6 @@ public: return false; // Must return a value in order to compile with VS 2005 } - /// getCallFrameSetup/DestroyOpcode - These methods return the opcode of the - /// frame setup/destroy instructions if they exist (-1 otherwise). Some - /// targets use pseudo instructions in order to abstract away the difference - /// between operating with a frame pointer and operating without, through the - /// use of these two instructions. - /// - int getCallFrameSetupOpcode() const { return CallFrameSetupOpcode; } - int getCallFrameDestroyOpcode() const { return CallFrameDestroyOpcode; } - /// eliminateCallFramePseudoInstr - This method is called during prolog/epilog /// code insertion to eliminate call frame setup and destroy pseudo /// instructions (but only if the Target is using them). It is responsible @@ -681,9 +669,6 @@ public: eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const { - assert(getCallFrameSetupOpcode()== -1 && getCallFrameDestroyOpcode()== -1 && - "eliminateCallFramePseudoInstr must be implemented if using" - " call frame setup/destroy pseudo instructions!"); assert(0 && "Call Frame Pseudo Instructions do not exist on this target!"); } diff --git a/lib/CodeGen/PrologEpilogInserter.cpp b/lib/CodeGen/PrologEpilogInserter.cpp index f1f3c99..a901c5f 100644 --- a/lib/CodeGen/PrologEpilogInserter.cpp +++ b/lib/CodeGen/PrologEpilogInserter.cpp @@ -145,6 +145,7 @@ void PEI::getAnalysisUsage(AnalysisUsage &AU) const { /// pseudo instructions. void PEI::calculateCallsInformation(MachineFunction &Fn) { const TargetRegisterInfo *RegInfo = Fn.getTarget().getRegisterInfo(); + const TargetInstrInfo &TII = *Fn.getTarget().getInstrInfo(); const TargetFrameLowering *TFI = Fn.getTarget().getFrameLowering(); MachineFrameInfo *MFI = Fn.getFrameInfo(); @@ -152,8 +153,8 @@ void PEI::calculateCallsInformation(MachineFunction &Fn) { bool AdjustsStack = MFI->adjustsStack(); // Get the function call frame set-up and tear-down instruction opcode - int FrameSetupOpcode = RegInfo->getCallFrameSetupOpcode(); - int FrameDestroyOpcode = RegInfo->getCallFrameDestroyOpcode(); + int FrameSetupOpcode = TII.getCallFrameSetupOpcode(); + int FrameDestroyOpcode = TII.getCallFrameDestroyOpcode(); // Early exit for targets which have no call frame setup/destroy pseudo // instructions. @@ -705,12 +706,13 @@ void PEI::replaceFrameIndices(MachineFunction &Fn) { const TargetMachine &TM = Fn.getTarget(); assert(TM.getRegisterInfo() && "TM::getRegisterInfo() must be implemented!"); + const TargetInstrInfo &TII = *Fn.getTarget().getInstrInfo(); const TargetRegisterInfo &TRI = *TM.getRegisterInfo(); const TargetFrameLowering *TFI = TM.getFrameLowering(); bool StackGrowsDown = TFI->getStackGrowthDirection() == TargetFrameLowering::StackGrowsDown; - int FrameSetupOpcode = TRI.getCallFrameSetupOpcode(); - int FrameDestroyOpcode = TRI.getCallFrameDestroyOpcode(); + int FrameSetupOpcode = TII.getCallFrameSetupOpcode(); + int FrameDestroyOpcode = TII.getCallFrameDestroyOpcode(); for (MachineFunction::iterator BB = Fn.begin(), E = Fn.end(); BB != E; ++BB) { diff --git a/lib/Target/ARM/ARMBaseInstrInfo.cpp b/lib/Target/ARM/ARMBaseInstrInfo.cpp index 31ea95a..6a6ba92 100644 --- a/lib/Target/ARM/ARMBaseInstrInfo.cpp +++ b/lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -77,7 +77,8 @@ static const ARM_MLxEntry ARM_MLxTable[] = { }; ARMBaseInstrInfo::ARMBaseInstrInfo(const ARMSubtarget& STI) - : TargetInstrInfoImpl(ARMInsts, array_lengthof(ARMInsts)), + : TargetInstrInfoImpl(ARMInsts, array_lengthof(ARMInsts), + ARM::ADJCALLSTACKDOWN, ARM::ADJCALLSTACKUP), Subtarget(STI) { for (unsigned i = 0, e = array_lengthof(ARM_MLxTable); i != e; ++i) { if (!MLxEntryMap.insert(std::make_pair(ARM_MLxTable[i].MLxOpc, i)).second) diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/lib/Target/ARM/ARMBaseRegisterInfo.cpp index fa937f3..f231089 100644 --- a/lib/Target/ARM/ARMBaseRegisterInfo.cpp +++ b/lib/Target/ARM/ARMBaseRegisterInfo.cpp @@ -58,8 +58,7 @@ EnableBasePointer("arm-use-base-pointer", cl::Hidden, cl::init(true), ARMBaseRegisterInfo::ARMBaseRegisterInfo(const ARMBaseInstrInfo &tii, const ARMSubtarget &sti) - : ARMGenRegisterInfo(ARM::ADJCALLSTACKDOWN, ARM::ADJCALLSTACKUP), - TII(tii), STI(sti), + : ARMGenRegisterInfo(), TII(tii), STI(sti), FramePtr((STI.isTargetDarwin() || STI.isThumb()) ? ARM::R7 : ARM::R11), BasePtr(ARM::R6) { } diff --git a/lib/Target/ARM/ARMFastISel.cpp b/lib/Target/ARM/ARMFastISel.cpp index e0409e9..f469d7e 100644 --- a/lib/Target/ARM/ARMFastISel.cpp +++ b/lib/Target/ARM/ARMFastISel.cpp @@ -1549,7 +1549,7 @@ bool ARMFastISel::ProcessCallArgs(SmallVectorImpl &Args, NumBytes = CCInfo.getNextStackOffset(); // Issue CALLSEQ_START - unsigned AdjStackDown = TM.getRegisterInfo()->getCallFrameSetupOpcode(); + unsigned AdjStackDown = TII.getCallFrameSetupOpcode(); AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(AdjStackDown)) .addImm(NumBytes)); @@ -1647,7 +1647,7 @@ bool ARMFastISel::FinishCall(MVT RetVT, SmallVectorImpl &UsedRegs, const Instruction *I, CallingConv::ID CC, unsigned &NumBytes) { // Issue CALLSEQ_END - unsigned AdjStackUp = TM.getRegisterInfo()->getCallFrameDestroyOpcode(); + unsigned AdjStackUp = TII.getCallFrameDestroyOpcode(); AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(AdjStackUp)) .addImm(NumBytes).addImm(0)); diff --git a/lib/Target/Alpha/AlphaInstrInfo.cpp b/lib/Target/Alpha/AlphaInstrInfo.cpp index 589e2d9..220f167 100644 --- a/lib/Target/Alpha/AlphaInstrInfo.cpp +++ b/lib/Target/Alpha/AlphaInstrInfo.cpp @@ -25,7 +25,8 @@ using namespace llvm; AlphaInstrInfo::AlphaInstrInfo() - : TargetInstrInfoImpl(AlphaInsts, array_lengthof(AlphaInsts)), + : TargetInstrInfoImpl(AlphaInsts, array_lengthof(AlphaInsts), + Alpha::ADJUSTSTACKDOWN, Alpha::ADJUSTSTACKUP), RI(*this) { } diff --git a/lib/Target/Alpha/AlphaRegisterInfo.cpp b/lib/Target/Alpha/AlphaRegisterInfo.cpp index b0bb7c0..0289307 100644 --- a/lib/Target/Alpha/AlphaRegisterInfo.cpp +++ b/lib/Target/Alpha/AlphaRegisterInfo.cpp @@ -41,7 +41,7 @@ using namespace llvm; AlphaRegisterInfo::AlphaRegisterInfo(const TargetInstrInfo &tii) - : AlphaGenRegisterInfo(Alpha::ADJUSTSTACKDOWN, Alpha::ADJUSTSTACKUP), + : AlphaGenRegisterInfo(), TII(tii) { } diff --git a/lib/Target/Blackfin/BlackfinInstrInfo.cpp b/lib/Target/Blackfin/BlackfinInstrInfo.cpp index 0b50a95..60da4c4 100644 --- a/lib/Target/Blackfin/BlackfinInstrInfo.cpp +++ b/lib/Target/Blackfin/BlackfinInstrInfo.cpp @@ -26,7 +26,8 @@ using namespace llvm; BlackfinInstrInfo::BlackfinInstrInfo(BlackfinSubtarget &ST) - : TargetInstrInfoImpl(BlackfinInsts, array_lengthof(BlackfinInsts)), + : TargetInstrInfoImpl(BlackfinInsts, array_lengthof(BlackfinInsts), + BF::ADJCALLSTACKDOWN, BF::ADJCALLSTACKUP), RI(ST, *this), Subtarget(ST) {} diff --git a/lib/Target/Blackfin/BlackfinRegisterInfo.cpp b/lib/Target/Blackfin/BlackfinRegisterInfo.cpp index e0fcce0..2f4a453 100644 --- a/lib/Target/Blackfin/BlackfinRegisterInfo.cpp +++ b/lib/Target/Blackfin/BlackfinRegisterInfo.cpp @@ -38,9 +38,7 @@ using namespace llvm; BlackfinRegisterInfo::BlackfinRegisterInfo(BlackfinSubtarget &st, const TargetInstrInfo &tii) - : BlackfinGenRegisterInfo(BF::ADJCALLSTACKDOWN, BF::ADJCALLSTACKUP), - Subtarget(st), - TII(tii) {} + : BlackfinGenRegisterInfo(), Subtarget(st), TII(tii) {} const unsigned* BlackfinRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { diff --git a/lib/Target/CellSPU/SPUInstrInfo.cpp b/lib/Target/CellSPU/SPUInstrInfo.cpp index 1107cff..5087b47 100644 --- a/lib/Target/CellSPU/SPUInstrInfo.cpp +++ b/lib/Target/CellSPU/SPUInstrInfo.cpp @@ -53,7 +53,8 @@ namespace { } SPUInstrInfo::SPUInstrInfo(SPUTargetMachine &tm) - : TargetInstrInfoImpl(SPUInsts, sizeof(SPUInsts)/sizeof(SPUInsts[0])), + : TargetInstrInfoImpl(SPUInsts, sizeof(SPUInsts)/sizeof(SPUInsts[0]), + SPU::ADJCALLSTACKDOWN, SPU::ADJCALLSTACKUP), TM(tm), RI(*TM.getSubtargetImpl(), *this) { /* NOP */ } diff --git a/lib/Target/CellSPU/SPURegisterInfo.cpp b/lib/Target/CellSPU/SPURegisterInfo.cpp index e37bc9b..fefd141 100644 --- a/lib/Target/CellSPU/SPURegisterInfo.cpp +++ b/lib/Target/CellSPU/SPURegisterInfo.cpp @@ -189,9 +189,7 @@ unsigned SPURegisterInfo::getRegisterNumbering(unsigned RegEnum) { SPURegisterInfo::SPURegisterInfo(const SPUSubtarget &subtarget, const TargetInstrInfo &tii) : - SPUGenRegisterInfo(SPU::ADJCALLSTACKDOWN, SPU::ADJCALLSTACKUP), - Subtarget(subtarget), - TII(tii) + SPUGenRegisterInfo(), Subtarget(subtarget), TII(tii) { } diff --git a/lib/Target/MBlaze/MBlazeInstrInfo.cpp b/lib/Target/MBlaze/MBlazeInstrInfo.cpp index adc81ff..a3af5d9 100644 --- a/lib/Target/MBlaze/MBlazeInstrInfo.cpp +++ b/lib/Target/MBlaze/MBlazeInstrInfo.cpp @@ -27,7 +27,8 @@ using namespace llvm; MBlazeInstrInfo::MBlazeInstrInfo(MBlazeTargetMachine &tm) - : TargetInstrInfoImpl(MBlazeInsts, array_lengthof(MBlazeInsts)), + : TargetInstrInfoImpl(MBlazeInsts, array_lengthof(MBlazeInsts), + MBlaze::ADJCALLSTACKDOWN, MBlaze::ADJCALLSTACKUP), TM(tm), RI(*TM.getSubtargetImpl(), *this) {} static bool isZeroImm(const MachineOperand &op) { diff --git a/lib/Target/MBlaze/MBlazeRegisterInfo.cpp b/lib/Target/MBlaze/MBlazeRegisterInfo.cpp index c370065..441ece1 100644 --- a/lib/Target/MBlaze/MBlazeRegisterInfo.cpp +++ b/lib/Target/MBlaze/MBlazeRegisterInfo.cpp @@ -45,8 +45,7 @@ using namespace llvm; MBlazeRegisterInfo:: MBlazeRegisterInfo(const MBlazeSubtarget &ST, const TargetInstrInfo &tii) - : MBlazeGenRegisterInfo(MBlaze::ADJCALLSTACKDOWN, MBlaze::ADJCALLSTACKUP), - Subtarget(ST), TII(tii) {} + : MBlazeGenRegisterInfo(), Subtarget(ST), TII(tii) {} /// getRegisterNumbering - Given the enum value for some register, e.g. /// MBlaze::R0, return the number that it corresponds to (e.g. 0). diff --git a/lib/Target/MSP430/MSP430InstrInfo.cpp b/lib/Target/MSP430/MSP430InstrInfo.cpp index b883f46..bf201b0 100644 --- a/lib/Target/MSP430/MSP430InstrInfo.cpp +++ b/lib/Target/MSP430/MSP430InstrInfo.cpp @@ -28,7 +28,8 @@ using namespace llvm; MSP430InstrInfo::MSP430InstrInfo(MSP430TargetMachine &tm) - : TargetInstrInfoImpl(MSP430Insts, array_lengthof(MSP430Insts)), + : TargetInstrInfoImpl(MSP430Insts, array_lengthof(MSP430Insts), + MSP430::ADJCALLSTACKDOWN, MSP430::ADJCALLSTACKUP), RI(tm, *this), TM(tm) {} void MSP430InstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, diff --git a/lib/Target/MSP430/MSP430RegisterInfo.cpp b/lib/Target/MSP430/MSP430RegisterInfo.cpp index eaa9947..da0c3c6 100644 --- a/lib/Target/MSP430/MSP430RegisterInfo.cpp +++ b/lib/Target/MSP430/MSP430RegisterInfo.cpp @@ -35,8 +35,7 @@ using namespace llvm; // FIXME: Provide proper call frame setup / destroy opcodes. MSP430RegisterInfo::MSP430RegisterInfo(MSP430TargetMachine &tm, const TargetInstrInfo &tii) - : MSP430GenRegisterInfo(MSP430::ADJCALLSTACKDOWN, MSP430::ADJCALLSTACKUP), - TM(tm), TII(tii) { + : MSP430GenRegisterInfo(), TM(tm), TII(tii) { StackAlign = TM.getFrameLowering()->getStackAlignment(); } @@ -121,12 +120,12 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, Amount = (Amount+StackAlign-1)/StackAlign*StackAlign; MachineInstr *New = 0; - if (Old->getOpcode() == getCallFrameSetupOpcode()) { + if (Old->getOpcode() == TII.getCallFrameSetupOpcode()) { New = BuildMI(MF, Old->getDebugLoc(), TII.get(MSP430::SUB16ri), MSP430::SPW) .addReg(MSP430::SPW).addImm(Amount); } else { - assert(Old->getOpcode() == getCallFrameDestroyOpcode()); + assert(Old->getOpcode() == TII.getCallFrameDestroyOpcode()); // factor out the amount the callee already popped. uint64_t CalleeAmt = Old->getOperand(1).getImm(); Amount -= CalleeAmt; @@ -144,7 +143,7 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MBB.insert(I, New); } } - } else if (I->getOpcode() == getCallFrameDestroyOpcode()) { + } else if (I->getOpcode() == TII.getCallFrameDestroyOpcode()) { // If we are performing frame pointer elimination and if the callee pops // something off the stack pointer, add it back. if (uint64_t CalleeAmt = I->getOperand(1).getImm()) { diff --git a/lib/Target/Mips/MipsInstrInfo.cpp b/lib/Target/Mips/MipsInstrInfo.cpp index a56c68b..508d1c2 100644 --- a/lib/Target/Mips/MipsInstrInfo.cpp +++ b/lib/Target/Mips/MipsInstrInfo.cpp @@ -25,7 +25,8 @@ using namespace llvm; MipsInstrInfo::MipsInstrInfo(MipsTargetMachine &tm) - : TargetInstrInfoImpl(MipsInsts, array_lengthof(MipsInsts)), + : TargetInstrInfoImpl(MipsInsts, array_lengthof(MipsInsts), + Mips::ADJCALLSTACKDOWN, Mips::ADJCALLSTACKUP), TM(tm), RI(*TM.getSubtargetImpl(), *this) {} static bool isZeroImm(const MachineOperand &op) { diff --git a/lib/Target/Mips/MipsRegisterInfo.cpp b/lib/Target/Mips/MipsRegisterInfo.cpp index 1025583..40774c9 100644 --- a/lib/Target/Mips/MipsRegisterInfo.cpp +++ b/lib/Target/Mips/MipsRegisterInfo.cpp @@ -44,8 +44,7 @@ using namespace llvm; MipsRegisterInfo::MipsRegisterInfo(const MipsSubtarget &ST, const TargetInstrInfo &tii) - : MipsGenRegisterInfo(Mips::ADJCALLSTACKDOWN, Mips::ADJCALLSTACKUP), - Subtarget(ST), TII(tii) {} + : MipsGenRegisterInfo(), Subtarget(ST), TII(tii) {} /// getRegisterNumbering - Given the enum value for some register, e.g. /// Mips::RA, return the number that it corresponds to (e.g. 31). diff --git a/lib/Target/PowerPC/PPCInstrInfo.cpp b/lib/Target/PowerPC/PPCInstrInfo.cpp index dade833..1ddc0f0 100644 --- a/lib/Target/PowerPC/PPCInstrInfo.cpp +++ b/lib/Target/PowerPC/PPCInstrInfo.cpp @@ -39,8 +39,9 @@ extern cl::opt EnablePPC64RS; // FIXME (64-bit): See PPCRegisterInfo.cpp. using namespace llvm; PPCInstrInfo::PPCInstrInfo(PPCTargetMachine &tm) - : TargetInstrInfoImpl(PPCInsts, array_lengthof(PPCInsts)), TM(tm), - RI(*TM.getSubtargetImpl(), *this) {} + : TargetInstrInfoImpl(PPCInsts, array_lengthof(PPCInsts), + PPC::ADJCALLSTACKDOWN, PPC::ADJCALLSTACKUP), + TM(tm), RI(*TM.getSubtargetImpl(), *this) {} /// CreateTargetHazardRecognizer - Return the hazard recognizer to use for /// this target when scheduling the DAG. diff --git a/lib/Target/PowerPC/PPCRegisterInfo.cpp b/lib/Target/PowerPC/PPCRegisterInfo.cpp index 91408cc..db139da 100644 --- a/lib/Target/PowerPC/PPCRegisterInfo.cpp +++ b/lib/Target/PowerPC/PPCRegisterInfo.cpp @@ -114,8 +114,7 @@ unsigned PPCRegisterInfo::getRegisterNumbering(unsigned RegEnum) { PPCRegisterInfo::PPCRegisterInfo(const PPCSubtarget &ST, const TargetInstrInfo &tii) - : PPCGenRegisterInfo(PPC::ADJCALLSTACKDOWN, PPC::ADJCALLSTACKUP), - Subtarget(ST), TII(tii) { + : PPCGenRegisterInfo(), Subtarget(ST), TII(tii) { ImmToIdxMap[PPC::LD] = PPC::LDX; ImmToIdxMap[PPC::STD] = PPC::STDX; ImmToIdxMap[PPC::LBZ] = PPC::LBZX; ImmToIdxMap[PPC::STB] = PPC::STBX; ImmToIdxMap[PPC::LHZ] = PPC::LHZX; ImmToIdxMap[PPC::LHA] = PPC::LHAX; diff --git a/lib/Target/Sparc/SparcInstrInfo.cpp b/lib/Target/Sparc/SparcInstrInfo.cpp index c323af8..e555b79 100644 --- a/lib/Target/Sparc/SparcInstrInfo.cpp +++ b/lib/Target/Sparc/SparcInstrInfo.cpp @@ -27,7 +27,8 @@ using namespace llvm; SparcInstrInfo::SparcInstrInfo(SparcSubtarget &ST) - : TargetInstrInfoImpl(SparcInsts, array_lengthof(SparcInsts)), + : TargetInstrInfoImpl(SparcInsts, array_lengthof(SparcInsts), + SP::ADJCALLSTACKDOWN, SP::ADJCALLSTACKUP), RI(ST, *this), Subtarget(ST) { } diff --git a/lib/Target/Sparc/SparcRegisterInfo.cpp b/lib/Target/Sparc/SparcRegisterInfo.cpp index 127b951..3b0b5fa 100644 --- a/lib/Target/Sparc/SparcRegisterInfo.cpp +++ b/lib/Target/Sparc/SparcRegisterInfo.cpp @@ -32,8 +32,7 @@ using namespace llvm; SparcRegisterInfo::SparcRegisterInfo(SparcSubtarget &st, const TargetInstrInfo &tii) - : SparcGenRegisterInfo(SP::ADJCALLSTACKDOWN, SP::ADJCALLSTACKUP), - Subtarget(st), TII(tii) { + : SparcGenRegisterInfo(), Subtarget(st), TII(tii) { } const unsigned* SparcRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) diff --git a/lib/Target/SystemZ/SystemZInstrInfo.cpp b/lib/Target/SystemZ/SystemZInstrInfo.cpp index b70e075..71ba9f9 100644 --- a/lib/Target/SystemZ/SystemZInstrInfo.cpp +++ b/lib/Target/SystemZ/SystemZInstrInfo.cpp @@ -29,7 +29,8 @@ using namespace llvm; SystemZInstrInfo::SystemZInstrInfo(SystemZTargetMachine &tm) - : TargetInstrInfoImpl(SystemZInsts, array_lengthof(SystemZInsts)), + : TargetInstrInfoImpl(SystemZInsts, array_lengthof(SystemZInsts), + SystemZ::ADJCALLSTACKUP, SystemZ::ADJCALLSTACKDOWN), RI(tm, *this), TM(tm) { } diff --git a/lib/Target/SystemZ/SystemZRegisterInfo.cpp b/lib/Target/SystemZ/SystemZRegisterInfo.cpp index 319cc46..21421a9 100644 --- a/lib/Target/SystemZ/SystemZRegisterInfo.cpp +++ b/lib/Target/SystemZ/SystemZRegisterInfo.cpp @@ -34,8 +34,7 @@ using namespace llvm; SystemZRegisterInfo::SystemZRegisterInfo(SystemZTargetMachine &tm, const SystemZInstrInfo &tii) - : SystemZGenRegisterInfo(SystemZ::ADJCALLSTACKUP, SystemZ::ADJCALLSTACKDOWN), - TM(tm), TII(tii) { + : SystemZGenRegisterInfo(), TM(tm), TII(tii) { } const unsigned* diff --git a/lib/Target/TargetInstrInfo.cpp b/lib/Target/TargetInstrInfo.cpp index 66f8f60..d30bb6c 100644 --- a/lib/Target/TargetInstrInfo.cpp +++ b/lib/Target/TargetInstrInfo.cpp @@ -24,7 +24,10 @@ using namespace llvm; // TargetInstrInfo //===----------------------------------------------------------------------===// -TargetInstrInfo::TargetInstrInfo(const MCInstrDesc* Desc, unsigned numOpcodes) { +TargetInstrInfo::TargetInstrInfo(const MCInstrDesc* Desc, unsigned numOpcodes, + int CFSetupOpcode, int CFDestroyOpcode) + : CallFrameSetupOpcode(CFSetupOpcode), + CallFrameDestroyOpcode(CFDestroyOpcode) { InitMCInstrInfo(Desc, numOpcodes); } diff --git a/lib/Target/TargetRegisterInfo.cpp b/lib/Target/TargetRegisterInfo.cpp index d01130a..90a8f8d 100644 --- a/lib/Target/TargetRegisterInfo.cpp +++ b/lib/Target/TargetRegisterInfo.cpp @@ -22,12 +22,9 @@ using namespace llvm; TargetRegisterInfo::TargetRegisterInfo(const TargetRegisterInfoDesc *ID, regclass_iterator RCB, regclass_iterator RCE, - const char *const *subregindexnames, - int CFSO, int CFDO) + const char *const *subregindexnames) : InfoDesc(ID), SubRegIndexNames(subregindexnames), RegClassBegin(RCB), RegClassEnd(RCE) { - CallFrameSetupOpcode = CFSO; - CallFrameDestroyOpcode = CFDO; } TargetRegisterInfo::~TargetRegisterInfo() {} diff --git a/lib/Target/X86/X86FastISel.cpp b/lib/Target/X86/X86FastISel.cpp index 09ce538..cdaa292 100644 --- a/lib/Target/X86/X86FastISel.cpp +++ b/lib/Target/X86/X86FastISel.cpp @@ -1630,7 +1630,7 @@ bool X86FastISel::DoSelectCall(const Instruction *I, const char *MemIntName) { unsigned NumBytes = CCInfo.getNextStackOffset(); // Issue CALLSEQ_START - unsigned AdjStackDown = TM.getRegisterInfo()->getCallFrameSetupOpcode(); + unsigned AdjStackDown = TII.getCallFrameSetupOpcode(); BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(AdjStackDown)) .addImm(NumBytes); @@ -1803,7 +1803,7 @@ bool X86FastISel::DoSelectCall(const Instruction *I, const char *MemIntName) { MIB.addReg(RegArgs[i]); // Issue CALLSEQ_END - unsigned AdjStackUp = TM.getRegisterInfo()->getCallFrameDestroyOpcode(); + unsigned AdjStackUp = TII.getCallFrameDestroyOpcode(); unsigned NumBytesCallee = 0; if (!Subtarget->is64Bit() && CS.paramHasAttr(1, Attribute::StructRet)) NumBytesCallee = 4; diff --git a/lib/Target/X86/X86InstrInfo.cpp b/lib/Target/X86/X86InstrInfo.cpp index 3112dc7..d44bd35 100644 --- a/lib/Target/X86/X86InstrInfo.cpp +++ b/lib/Target/X86/X86InstrInfo.cpp @@ -54,7 +54,13 @@ ReMatPICStubLoad("remat-pic-stub-load", cl::init(false), cl::Hidden); X86InstrInfo::X86InstrInfo(X86TargetMachine &tm) - : TargetInstrInfoImpl(X86Insts, array_lengthof(X86Insts)), + : TargetInstrInfoImpl(X86Insts, array_lengthof(X86Insts), + (tm.getSubtarget().is64Bit() + ? X86::ADJCALLSTACKDOWN64 + : X86::ADJCALLSTACKDOWN32), + (tm.getSubtarget().is64Bit() + ? X86::ADJCALLSTACKUP64 + : X86::ADJCALLSTACKUP32)), TM(tm), RI(tm, *this) { enum { TB_NOT_REVERSABLE = 1U << 31, diff --git a/lib/Target/X86/X86RegisterInfo.cpp b/lib/Target/X86/X86RegisterInfo.cpp index d771d40..90b333f 100644 --- a/lib/Target/X86/X86RegisterInfo.cpp +++ b/lib/Target/X86/X86RegisterInfo.cpp @@ -54,13 +54,7 @@ ForceStackAlign("force-align-stack", X86RegisterInfo::X86RegisterInfo(X86TargetMachine &tm, const TargetInstrInfo &tii) - : X86GenRegisterInfo(tm.getSubtarget().is64Bit() ? - X86::ADJCALLSTACKDOWN64 : - X86::ADJCALLSTACKDOWN32, - tm.getSubtarget().is64Bit() ? - X86::ADJCALLSTACKUP64 : - X86::ADJCALLSTACKUP32), - TM(tm), TII(tii) { + : X86GenRegisterInfo(), TM(tm), TII(tii) { // Cache some information. const X86Subtarget *Subtarget = &TM.getSubtarget(); Is64Bit = Subtarget->is64Bit(); @@ -608,7 +602,7 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); bool reseveCallFrame = TFI->hasReservedCallFrame(MF); int Opcode = I->getOpcode(); - bool isDestroy = Opcode == getCallFrameDestroyOpcode(); + bool isDestroy = Opcode == TII.getCallFrameDestroyOpcode(); DebugLoc DL = I->getDebugLoc(); uint64_t Amount = !reseveCallFrame ? I->getOperand(0).getImm() : 0; uint64_t CalleeAmt = isDestroy ? I->getOperand(1).getImm() : 0; @@ -629,13 +623,13 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, Amount = (Amount + StackAlign - 1) / StackAlign * StackAlign; MachineInstr *New = 0; - if (Opcode == getCallFrameSetupOpcode()) { + if (Opcode == TII.getCallFrameSetupOpcode()) { New = BuildMI(MF, DL, TII.get(getSUBriOpcode(Is64Bit, Amount)), StackPtr) .addReg(StackPtr) .addImm(Amount); } else { - assert(Opcode == getCallFrameDestroyOpcode()); + assert(Opcode == TII.getCallFrameDestroyOpcode()); // Factor out the amount the callee already popped. Amount -= CalleeAmt; @@ -658,7 +652,7 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, return; } - if (Opcode == getCallFrameDestroyOpcode() && CalleeAmt) { + if (Opcode == TII.getCallFrameDestroyOpcode() && CalleeAmt) { // If we are performing frame pointer elimination and if the callee pops // something off the stack pointer, add it back. We do this until we have // more advanced stack pointer tracking ability. diff --git a/lib/Target/XCore/XCoreInstrInfo.cpp b/lib/Target/XCore/XCoreInstrInfo.cpp index 97a1d52..cb54520 100644 --- a/lib/Target/XCore/XCoreInstrInfo.cpp +++ b/lib/Target/XCore/XCoreInstrInfo.cpp @@ -40,7 +40,8 @@ namespace XCore { using namespace llvm; XCoreInstrInfo::XCoreInstrInfo() - : TargetInstrInfoImpl(XCoreInsts, array_lengthof(XCoreInsts)), + : TargetInstrInfoImpl(XCoreInsts, array_lengthof(XCoreInsts), + XCore::ADJCALLSTACKDOWN, XCore::ADJCALLSTACKUP), RI(*this) { } diff --git a/lib/Target/XCore/XCoreRegisterInfo.cpp b/lib/Target/XCore/XCoreRegisterInfo.cpp index ecb9e80..2bf43b4 100644 --- a/lib/Target/XCore/XCoreRegisterInfo.cpp +++ b/lib/Target/XCore/XCoreRegisterInfo.cpp @@ -40,8 +40,7 @@ using namespace llvm; XCoreRegisterInfo::XCoreRegisterInfo(const TargetInstrInfo &tii) - : XCoreGenRegisterInfo(XCore::ADJCALLSTACKDOWN, XCore::ADJCALLSTACKUP), - TII(tii) { + : XCoreGenRegisterInfo(), TII(tii) { } // helper functions diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp index bf27053..abb8624 100644 --- a/utils/TableGen/RegisterInfoEmitter.cpp +++ b/utils/TableGen/RegisterInfoEmitter.cpp @@ -214,8 +214,7 @@ RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target, OS << "namespace llvm {\n\n"; OS << "struct " << ClassName << " : public TargetRegisterInfo {\n" - << " explicit " << ClassName - << "(int CallFrameSetupOpcode = -1, int CallFrameDestroyOpcode = -1);\n" + << " explicit " << ClassName << "();\n" << " virtual int getDwarfRegNumFull(unsigned RegNum, " << "unsigned Flavour) const;\n" << " virtual int getLLVMRegNumFull(unsigned DwarfRegNum, " @@ -660,11 +659,10 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, // Emit the constructor of the class... OS << ClassName << "::" << ClassName - << "(int CallFrameSetupOpcode, int CallFrameDestroyOpcode)\n" + << "()\n" << " : TargetRegisterInfo(" << TargetName << "RegInfoDesc" << ", RegisterClasses, RegisterClasses+" << RegisterClasses.size() <<",\n" - << " SubRegIndexTable,\n" - << " CallFrameSetupOpcode, CallFrameDestroyOpcode) {\n" + << " SubRegIndexTable) {\n" << " InitMCRegisterInfo(" << TargetName << "RegDesc, " << Regs.size()+1 << ");\n" << "}\n\n"; -- cgit v1.1 From a01b58af85cebd7d7bcf94d48317f8cc8a4bdf57 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Tue, 28 Jun 2011 21:33:11 +0000 Subject: Unbreak every backend. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134031 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Target/TargetInstrInfo.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h index 980a537..70969eb 100644 --- a/include/llvm/Target/TargetInstrInfo.h +++ b/include/llvm/Target/TargetInstrInfo.h @@ -681,7 +681,8 @@ protected: TargetInstrInfoImpl(const MCInstrDesc *desc, unsigned NumOpcodes, int CallFrameSetupOpcode = -1, int CallFrameDestroyOpcode = -1) - : TargetInstrInfo(desc, NumOpcodes) {} + : TargetInstrInfo(desc, NumOpcodes, + CallFrameSetupOpcode, CallFrameDestroyOpcode) {} public: virtual void ReplaceTailWithBranchTo(MachineBasicBlock::iterator OldInst, MachineBasicBlock *NewDest) const; -- cgit v1.1 From 5876298e36b29a4cd723fbc447ffa4dc1a7dc198 Mon Sep 17 00:00:00 2001 From: NAKAMURA Takumi Date: Tue, 28 Jun 2011 21:46:21 +0000 Subject: Fix a CMake warning, following up to r134008. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134033 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index b08c7ae..9fc76a9 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -85,7 +85,7 @@ if(PYTHONINTERP_FOUND) set(ENABLE_ASSERTIONS "1") else() set(ENABLE_ASSERTIONS "0") - endif(LLVM_ENABLE_ASSERTIONS) + endif() configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in -- cgit v1.1 From ade490a8297f7d7c9763ef173ce8b7607355b4e7 Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Tue, 28 Jun 2011 22:30:17 +0000 Subject: build/Darwin: Fix epic typo fail. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134036 91177308-0d34-0410-b5e6-96231b3b80d8 --- Makefile.rules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.rules b/Makefile.rules index 46a3f1b..19520dd 100644 --- a/Makefile.rules +++ b/Makefile.rules @@ -1377,7 +1377,7 @@ endif #--------------------------------------------------------- ifeq ($(HOST_OS),Darwin) -ifdef TOOL_ORDER_FINE +ifdef TOOL_ORDER_FILE LD.Flags += -Wl,-order_file,$(TOOL_ORDER_FILE) -- cgit v1.1 From 4d517e34e5c8431adb724c94a14b02362a9cfe67 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Wed, 29 Jun 2011 00:24:24 +0000 Subject: Rewrite RAGreedy::splitAroundRegion, now with cool ASCII art. This function has to deal with a lot of special cases, and the old version got it wrong sometimes. In particular, it would sometimes leave multiple uses in the stack interval in a single block. That causes bad code with multiple reloads in the same basic block. The new version handles block entry and exit in a single pass. It first eliminates all the easy cases, and then goes on to create a local interval for the blocks with difficult interference. Previously, we would only create the local interval for completely isolated blocks. It can happen that the stack interval becomes completely empty because we could allocate a register in all edge bundles, and the new local intervals deal with the interference. The empty stack interval is harmless, but we need to remove a SplitKit assertion that checks for empty intervals. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134047 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/RegAllocGreedy.cpp | 394 +++++++++++++++++++++++++++-------------- lib/CodeGen/SplitKit.cpp | 25 ++- lib/CodeGen/SplitKit.h | 10 ++ 3 files changed, 291 insertions(+), 138 deletions(-) diff --git a/lib/CodeGen/RegAllocGreedy.cpp b/lib/CodeGen/RegAllocGreedy.cpp index d0e6a64..912d899 100644 --- a/lib/CodeGen/RegAllocGreedy.cpp +++ b/lib/CodeGen/RegAllocGreedy.cpp @@ -763,32 +763,46 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg, // Create the main cross-block interval. const unsigned MainIntv = SE->openIntv(); - // First add all defs that are live out of a block. + // First handle all the blocks with uses. ArrayRef UseBlocks = SA->getUseBlocks(); for (unsigned i = 0; i != UseBlocks.size(); ++i) { const SplitAnalysis::BlockInfo &BI = UseBlocks[i]; - bool RegIn = LiveBundles[Bundles->getBundle(BI.MBB->getNumber(), 0)]; - bool RegOut = LiveBundles[Bundles->getBundle(BI.MBB->getNumber(), 1)]; + bool RegIn = BI.LiveIn && + LiveBundles[Bundles->getBundle(BI.MBB->getNumber(), 0)]; + bool RegOut = BI.LiveOut && + LiveBundles[Bundles->getBundle(BI.MBB->getNumber(), 1)]; // Create separate intervals for isolated blocks with multiple uses. - if (!RegIn && !RegOut && BI.FirstUse != BI.LastUse) { + // + // |---o---o---| Enter and leave on the stack. + // ____-----____ Create local interval for uses. + // + // | o---o---| Defined in block, leave on stack. + // -----____ Create local interval for uses. + // + // |---o---x | Enter on stack, killed in block. + // ____----- Create local interval for uses. + // + if (!RegIn && !RegOut) { DEBUG(dbgs() << "BB#" << BI.MBB->getNumber() << " isolated.\n"); - SE->splitSingleBlock(BI); - SE->selectIntv(MainIntv); + if (!BI.isOneInstr()) { + SE->splitSingleBlock(BI); + SE->selectIntv(MainIntv); + } continue; } - // Should the register be live out? - if (!BI.LiveOut || !RegOut) - continue; - SlotIndex Start, Stop; tie(Start, Stop) = Indexes->getMBBRange(BI.MBB); Intf.moveToBlock(BI.MBB->getNumber()); - DEBUG(dbgs() << "BB#" << BI.MBB->getNumber() << " -> EB#" - << Bundles->getBundle(BI.MBB->getNumber(), 1) + DEBUG(dbgs() << "EB#" << Bundles->getBundle(BI.MBB->getNumber(), 0) + << (RegIn ? " => " : " -- ") + << "BB#" << BI.MBB->getNumber() + << (RegOut ? " => " : " -- ") + << " EB#" << Bundles->getBundle(BI.MBB->getNumber(), 1) << " [" << Start << ';' << SA->getLastSplitPoint(BI.MBB->getNumber()) << '-' << Stop + << ") uses [" << BI.FirstUse << ';' << BI.LastUse << ") intf [" << Intf.first() << ';' << Intf.last() << ')'); // The interference interval should either be invalid or overlap MBB. @@ -797,150 +811,266 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg, assert((!Intf.hasInterference() || Intf.last() > Start) && "Bad interference"); - // Check interference leaving the block. + // We are now ready to decide where to split in the current block. There + // are many variables guiding the decision: + // + // - RegIn / RegOut: The global splitting algorithm's decisions for our + // ingoing and outgoing bundles. + // + // - BI.BlockIn / BI.BlockOut: Is the live range live-in and/or live-out + // from this block. + // + // - Intf.hasInterference(): Is there interference in this block. + // + // - Intf.first() / Inft.last(): The range of interference. + // + // The live range should be split such that MainIntv is live-in when RegIn + // is set, and live-out when RegOut is set. MainIntv should never overlap + // the interference, and the stack interval should never have more than one + // use per block. + + // No splits can be inserted after LastSplitPoint, overlap instead. + SlotIndex LastSplitPoint = Stop; + if (BI.LiveOut) + LastSplitPoint = SA->getLastSplitPoint(BI.MBB->getNumber()); + + // At this point, we know that either RegIn or RegOut is set. We dealt with + // the all-stack case above. + + // Blocks without interference are relatively easy. if (!Intf.hasInterference()) { - // Block is interference-free. - DEBUG(dbgs() << ", no interference"); - if (!BI.LiveThrough) { - DEBUG(dbgs() << ", not live-through.\n"); - SE->useIntv(SE->enterIntvBefore(BI.FirstUse), Stop); - continue; - } - if (!RegIn) { - // Block is live-through, but entry bundle is on the stack. - // Reload just before the first use. - DEBUG(dbgs() << ", not live-in, enter before first use.\n"); - SE->useIntv(SE->enterIntvBefore(BI.FirstUse), Stop); - continue; + DEBUG(dbgs() << ", no interference.\n"); + SE->selectIntv(MainIntv); + // The easiest case has MainIntv live through. + // + // |---o---o---| Live-in, live-out. + // ============= Use MainIntv everywhere. + // + SlotIndex From = Start, To = Stop; + + // Block entry. Reload before the first use if MainIntv is not live-in. + // + // |---o-- Enter on stack. + // ____=== Reload before first use. + // + // | o-- Defined in block. + // === Use MainIntv from def. + // + if (!RegIn) + From = SE->enterIntvBefore(BI.FirstUse); + + // Block exit. Handle cases where MainIntv is not live-out. + if (!BI.LiveOut) + // + // --x | Killed in block. + // === Use MainIntv up to kill. + // + To = SE->leaveIntvAfter(BI.LastUse); + else if (!RegOut) { + // + // --o---| Live-out on stack. + // ===____ Use MainIntv up to last use, switch to stack. + // + // -----o| Live-out on stack, last use after last split point. + // ====== Extend MainIntv to last use, overlapping. + // \____ Copy to stack interval before last split point. + // + if (BI.LastUse < LastSplitPoint) + To = SE->leaveIntvAfter(BI.LastUse); + else { + // The last use is after the last split point, it is probably an + // indirect branch. + To = SE->leaveIntvBefore(LastSplitPoint); + // Run a double interval from the split to the last use. This makes + // it possible to spill the complement without affecting the indirect + // branch. + SE->overlapIntv(To, BI.LastUse); + } } - DEBUG(dbgs() << ", live-through.\n"); - continue; - } - - // Block has interference. - DEBUG(dbgs() << ", interference to " << Intf.last()); - if (!BI.LiveThrough && Intf.last() <= BI.FirstUse) { - // The interference doesn't reach the outgoing segment. - DEBUG(dbgs() << " doesn't affect def from " << BI.FirstUse << '\n'); - SE->useIntv(BI.FirstUse, Stop); + // Paint in MainIntv liveness for this block. + SE->useIntv(From, To); continue; } - SlotIndex LastSplitPoint = SA->getLastSplitPoint(BI.MBB->getNumber()); - if (Intf.last().getBoundaryIndex() < BI.LastUse) { - // There are interference-free uses at the end of the block. - // Find the first use that can get the live-out register. - SmallVectorImpl::const_iterator UI = - std::lower_bound(SA->UseSlots.begin(), SA->UseSlots.end(), - Intf.last().getBoundaryIndex()); - assert(UI != SA->UseSlots.end() && "Couldn't find last use"); - SlotIndex Use = *UI; - assert(Use <= BI.LastUse && "Couldn't find last use"); - // Only attempt a split befroe the last split point. - if (Use.getBaseIndex() <= LastSplitPoint) { - DEBUG(dbgs() << ", free use at " << Use << ".\n"); - SlotIndex SegStart = SE->enterIntvBefore(Use); - assert(SegStart >= Intf.last() && "Couldn't avoid interference"); - assert(SegStart < LastSplitPoint && "Impossible split point"); - SE->useIntv(SegStart, Stop); - continue; - } - } + // We are now looking at a block with interference, and we know that either + // RegIn or RegOut is set. + assert(Intf.hasInterference() && (RegIn || RegOut) && "Bad invariant"); - // Interference is after the last use. - DEBUG(dbgs() << " after last use.\n"); - SlotIndex SegStart = SE->enterIntvAtEnd(*BI.MBB); - assert(SegStart >= Intf.last() && "Couldn't avoid interference"); - } + // If the live range is not live through the block, it is possible that the + // interference doesn't even overlap. Deal with those cases first. Since + // no copy instructions are required, we can tolerate interference starting + // or ending at the same instruction that kills or defines our live range. - // Now all defs leading to live bundles are handled, do everything else. - for (unsigned i = 0; i != UseBlocks.size(); ++i) { - const SplitAnalysis::BlockInfo &BI = UseBlocks[i]; - bool RegIn = LiveBundles[Bundles->getBundle(BI.MBB->getNumber(), 0)]; - bool RegOut = LiveBundles[Bundles->getBundle(BI.MBB->getNumber(), 1)]; + // Live-in, killed before interference. + // + // ~~~ Interference after kill. + // |---o---x | Killed in block. + // ========= Use MainIntv everywhere. + // + if (RegIn && !BI.LiveOut && BI.LastUse <= Intf.first()) { + DEBUG(dbgs() << ", live-in, killed before interference.\n"); + SE->selectIntv(MainIntv); + SlotIndex To = SE->leaveIntvAfter(BI.LastUse); + SE->useIntv(Start, To); + continue; + } - // Is the register live-in? - if (!BI.LiveIn || !RegIn) + // Live-out, defined after interference. + // + // ~~~ Interference before def. + // | o---o---| Defined in block. + // ========= Use MainIntv everywhere. + // + if (RegOut && !BI.LiveIn && BI.FirstUse >= Intf.last()) { + DEBUG(dbgs() << ", live-out, defined after interference.\n"); + SE->selectIntv(MainIntv); + SlotIndex From = SE->enterIntvBefore(BI.FirstUse); + SE->useIntv(From, Stop); continue; + } - // We have an incoming register. Check for interference. - SlotIndex Start, Stop; - tie(Start, Stop) = Indexes->getMBBRange(BI.MBB); - Intf.moveToBlock(BI.MBB->getNumber()); - DEBUG(dbgs() << "EB#" << Bundles->getBundle(BI.MBB->getNumber(), 0) - << " -> BB#" << BI.MBB->getNumber() << " [" << Start << ';' - << SA->getLastSplitPoint(BI.MBB->getNumber()) << '-' << Stop - << ')'); + // The interference is now known to overlap the live range, but it may + // still be easy to avoid if all the interference is on one side of the + // uses, and we enter or leave on the stack. - // Check interference entering the block. - if (!Intf.hasInterference()) { - // Block is interference-free. - DEBUG(dbgs() << ", no interference"); - if (!BI.LiveThrough) { - DEBUG(dbgs() << ", killed in block.\n"); - SE->useIntv(Start, SE->leaveIntvAfter(BI.LastUse)); - continue; - } - if (!RegOut) { - SlotIndex LastSplitPoint = SA->getLastSplitPoint(BI.MBB->getNumber()); - // Block is live-through, but exit bundle is on the stack. - // Spill immediately after the last use. - if (BI.LastUse < LastSplitPoint) { - DEBUG(dbgs() << ", uses, stack-out.\n"); - SE->useIntv(Start, SE->leaveIntvAfter(BI.LastUse)); - continue; - } - // The last use is after the last split point, it is probably an - // indirect jump. - DEBUG(dbgs() << ", uses at " << BI.LastUse << " after split point " - << LastSplitPoint << ", stack-out.\n"); - SlotIndex SegEnd = SE->leaveIntvBefore(LastSplitPoint); - SE->useIntv(Start, SegEnd); - // Run a double interval from the split to the last use. - // This makes it possible to spill the complement without affecting the - // indirect branch. - SE->overlapIntv(SegEnd, BI.LastUse); - continue; + // Live-out on stack, interference after last use. + // + // ~~~ Interference after last use. + // |---o---o---| Live-out on stack. + // =========____ Leave MainIntv after last use. + // + // ~ Interference after last use. + // |---o---o--o| Live-out on stack, late last use. + // =========____ Copy to stack after LSP, overlap MainIntv. + // + if (!RegOut && Intf.first() > BI.LastUse.getBoundaryIndex()) { + assert(RegIn && "Stack-in, stack-out should already be handled"); + if (BI.LastUse < LastSplitPoint) { + DEBUG(dbgs() << ", live-in, stack-out, interference after last use.\n"); + SE->selectIntv(MainIntv); + SlotIndex To = SE->leaveIntvAfter(BI.LastUse); + assert(To <= Intf.first() && "Expected to avoid interference"); + SE->useIntv(Start, To); + } else { + DEBUG(dbgs() << ", live-in, stack-out, avoid last split point\n"); + SE->selectIntv(MainIntv); + SlotIndex To = SE->leaveIntvBefore(LastSplitPoint); + assert(To <= Intf.first() && "Expected to avoid interference"); + SE->overlapIntv(To, BI.LastUse); + SE->useIntv(Start, To); } - // Register is live-through. - DEBUG(dbgs() << ", uses, live-through.\n"); - SE->useIntv(Start, Stop); continue; } - // Block has interference. - DEBUG(dbgs() << ", interference from " << Intf.first()); - - if (!BI.LiveThrough && Intf.first() >= BI.LastUse) { - // The interference doesn't reach the outgoing segment. - DEBUG(dbgs() << " doesn't affect kill at " << BI.LastUse << '\n'); - SE->useIntv(Start, BI.LastUse); + // Live-in on stack, interference before first use. + // + // ~~~ Interference before first use. + // |---o---o---| Live-in on stack. + // ____========= Enter MainIntv before first use. + // + if (!RegIn && Intf.last() < BI.FirstUse.getBaseIndex()) { + assert(RegOut && "Stack-in, stack-out should already be handled"); + DEBUG(dbgs() << ", stack-in, interference before first use.\n"); + SE->selectIntv(MainIntv); + SlotIndex From = SE->enterIntvBefore(BI.FirstUse); + assert(From >= Intf.last() && "Expected to avoid interference"); + SE->useIntv(From, Stop); continue; } - if (Intf.first().getBaseIndex() > BI.FirstUse) { - // There are interference-free uses at the beginning of the block. - // Find the last use that can get the register. - SmallVectorImpl::const_iterator UI = - std::lower_bound(SA->UseSlots.begin(), SA->UseSlots.end(), - Intf.first().getBaseIndex()); - assert(UI != SA->UseSlots.begin() && "Couldn't find first use"); - SlotIndex Use = (--UI)->getBoundaryIndex(); - DEBUG(dbgs() << ", free use at " << *UI << ".\n"); - SlotIndex SegEnd = SE->leaveIntvAfter(Use); - assert(SegEnd <= Intf.first() && "Couldn't avoid interference"); - SE->useIntv(Start, SegEnd); - continue; + // The interference is overlapping somewhere we wanted to use MainIntv. That + // means we need to create a local interval that can be allocated a + // different register. + DEBUG(dbgs() << ", creating local interval.\n"); + unsigned LocalIntv = SE->openIntv(); + + // We may be creating copies directly between MainIntv and LocalIntv, + // bypassing the stack interval. When we do that, we should never use the + // leaveIntv* methods as they define values in the stack interval. By + // starting from the end of the block and working our way backwards, we can + // get by with only enterIntv* methods. + // + // When selecting split points, we generally try to maximize the stack + // interval as long at it contains no uses, maximize the main interval as + // long as it doesn't overlap interference, and minimize the local interval + // that we don't know how to allocate yet. + + // Handle the block exit, set Pos to the first handled slot. + SlotIndex Pos = BI.LastUse; + if (RegOut) { + assert(Intf.last() < LastSplitPoint && "Cannot be live-out in register"); + // Create a snippet of MainIntv that is live-out. + // + // ~~~ Interference overlapping uses. + // --o---| Live-out in MainIntv. + // ----=== Switch from LocalIntv to MainIntv after interference. + // + SE->selectIntv(MainIntv); + Pos = SE->enterIntvAfter(Intf.last()); + assert(Pos >= Intf.last() && "Expected to avoid interference"); + SE->useIntv(Pos, Stop); + SE->selectIntv(LocalIntv); + } else if (BI.LiveOut) { + if (BI.LastUse < LastSplitPoint) { + // Live-out on the stack. + // + // ~~~ Interference overlapping uses. + // --o---| Live-out on stack. + // ---____ Switch from LocalIntv to stack after last use. + // + Pos = SE->leaveIntvAfter(BI.LastUse); + } else { + // Live-out on the stack, last use after last split point. + // + // ~~~ Interference overlapping uses. + // --o--o| Live-out on stack, late use. + // ------ Copy to stack before LSP, overlap LocalIntv. + // \__ + // + Pos = SE->leaveIntvBefore(LastSplitPoint); + // We need to overlap LocalIntv so it can reach LastUse. + SE->overlapIntv(Pos, BI.LastUse); + } } - // Interference is before the first use. - DEBUG(dbgs() << " before first use.\n"); - SlotIndex SegEnd = SE->leaveIntvAtTop(*BI.MBB); - assert(SegEnd <= Intf.first() && "Couldn't avoid interference"); + // When not live-out, leave Pos at LastUse. We have handled everything from + // Pos to Stop. Find the starting point for LocalIntv. + assert(SE->currentIntv() == LocalIntv && "Expecting local interval"); + + if (RegIn) { + assert(Start < Intf.first() && "Cannot be live-in with interference"); + // Live-in in MainIntv, only use LocalIntv for interference. + // + // ~~~ Interference overlapping uses. + // |---o-- Live-in in MainIntv. + // ====--- Switch to LocalIntv before interference. + // + SlotIndex Switch = SE->enterIntvBefore(Intf.first()); + assert(Switch <= Intf.first() && "Expected to avoid interference"); + SE->useIntv(Switch, Pos); + SE->selectIntv(MainIntv); + SE->useIntv(Start, Switch); + } else { + // Live-in on stack, enter LocalIntv before first use. + // + // ~~~ Interference overlapping uses. + // |---o-- Live-in in MainIntv. + // ____--- Reload to LocalIntv before interference. + // + // Defined in block. + // + // ~~~ Interference overlapping uses. + // | o-- Defined in block. + // --- Begin LocalIntv at first use. + // + SlotIndex Switch = SE->enterIntvBefore(BI.FirstUse); + SE->useIntv(Switch, Pos); + } } // Handle live-through blocks. + SE->selectIntv(MainIntv); for (unsigned i = 0, e = Cand.ActiveBlocks.size(); i != e; ++i) { unsigned Number = Cand.ActiveBlocks[i]; bool RegIn = LiveBundles[Bundles->getBundle(Number, 0)]; diff --git a/lib/CodeGen/SplitKit.cpp b/lib/CodeGen/SplitKit.cpp index 55b1114..a0952a0 100644 --- a/lib/CodeGen/SplitKit.cpp +++ b/lib/CodeGen/SplitKit.cpp @@ -636,6 +636,7 @@ unsigned SplitEditor::openIntv() { void SplitEditor::selectIntv(unsigned Idx) { assert(Idx != 0 && "Cannot select the complement interval"); assert(Idx < Edit->size() && "Can only select previously opened interval"); + DEBUG(dbgs() << " selectIntv " << OpenIdx << " -> " << Idx << '\n'); OpenIdx = Idx; } @@ -656,6 +657,24 @@ SlotIndex SplitEditor::enterIntvBefore(SlotIndex Idx) { return VNI->def; } +SlotIndex SplitEditor::enterIntvAfter(SlotIndex Idx) { + assert(OpenIdx && "openIntv not called before enterIntvAfter"); + DEBUG(dbgs() << " enterIntvAfter " << Idx); + Idx = Idx.getBoundaryIndex(); + VNInfo *ParentVNI = Edit->getParent().getVNInfoAt(Idx); + if (!ParentVNI) { + DEBUG(dbgs() << ": not live\n"); + return Idx; + } + DEBUG(dbgs() << ": valno " << ParentVNI->id << '\n'); + MachineInstr *MI = LIS.getInstructionFromIndex(Idx); + assert(MI && "enterIntvAfter called with invalid index"); + + VNInfo *VNI = defFromParent(OpenIdx, ParentVNI, Idx, *MI->getParent(), + llvm::next(MachineBasicBlock::iterator(MI))); + return VNI->def; +} + SlotIndex SplitEditor::enterIntvAtEnd(MachineBasicBlock &MBB) { assert(OpenIdx && "openIntv not called before enterIntvAtEnd"); SlotIndex End = LIS.getMBBEndIdx(&MBB); @@ -1007,12 +1026,6 @@ void SplitEditor::finish(SmallVectorImpl *LRMap) { markComplexMapped(i, ParentVNI); } -#ifndef NDEBUG - // Every new interval must have a def by now, otherwise the split is bogus. - for (LiveRangeEdit::iterator I = Edit->begin(), E = Edit->end(); I != E; ++I) - assert((*I)->hasAtLeastOneValue() && "Split interval has no value"); -#endif - // Transfer the simply mapped values, check if any are skipped. bool Skipped = transferValues(); if (Skipped) diff --git a/lib/CodeGen/SplitKit.h b/lib/CodeGen/SplitKit.h index 7174c0b..a9ccf40b 100644 --- a/lib/CodeGen/SplitKit.h +++ b/lib/CodeGen/SplitKit.h @@ -81,6 +81,12 @@ public: bool LiveThrough; ///< Live in whole block (Templ 5. above). bool LiveIn; ///< Current reg is live in. bool LiveOut; ///< Current reg is live out. + + /// isOneInstr - Returns true when this BlockInfo describes a single + /// instruction. + bool isOneInstr() const { + return SlotIndex::isSameInstr(FirstUse, LastUse); + } }; private: @@ -360,6 +366,10 @@ public: /// Return the beginning of the new live range. SlotIndex enterIntvBefore(SlotIndex Idx); + /// enterIntvAfter - Enter the open interval after the instruction at Idx. + /// Return the beginning of the new live range. + SlotIndex enterIntvAfter(SlotIndex Idx); + /// enterIntvAtEnd - Enter the open interval at the end of MBB. /// Use the open interval from he inserted copy to the MBB end. /// Return the beginning of the new live range. -- cgit v1.1 From d807674c8b1a8d191a4e52795fd6a3a6de184116 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Wed, 29 Jun 2011 00:35:31 +0000 Subject: Trim include git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134048 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Target/SubtargetFeature.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/llvm/Target/SubtargetFeature.h b/include/llvm/Target/SubtargetFeature.h index 4213d9b..cbd2c3b 100644 --- a/include/llvm/Target/SubtargetFeature.h +++ b/include/llvm/Target/SubtargetFeature.h @@ -20,7 +20,6 @@ #include #include -#include #include "llvm/ADT/Triple.h" #include "llvm/Support/DataTypes.h" -- cgit v1.1 From ab8be96fd30ca9396e6b84fdddf1ac6208984cad Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Wed, 29 Jun 2011 01:14:12 +0000 Subject: Sink SubtargetFeature and TargetInstrItineraries (renamed MCInstrItineraries) into MC. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134049 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/MC/MCInstrItineraries.h | 253 ++++++++++++++++ include/llvm/MC/SubtargetFeature.h | 118 ++++++++ include/llvm/Target/SubtargetFeature.h | 118 -------- include/llvm/Target/TargetInstrItineraries.h | 253 ---------------- include/llvm/Target/TargetMachine.h | 22 +- lib/CodeGen/IfConversion.cpp | 2 +- lib/CodeGen/MachineLICM.cpp | 2 +- lib/CodeGen/ScheduleDAGInstrs.cpp | 1 + lib/CodeGen/ScoreboardHazardRecognizer.cpp | 2 +- lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp | 1 + lib/ExecutionEngine/TargetSelect.cpp | 2 +- lib/MC/SubtargetFeature.cpp | 384 ++++++++++++++++++++++++ lib/Target/ARM/ARMSubtarget.h | 3 +- lib/Target/Alpha/AlphaSubtarget.h | 3 +- lib/Target/CellSPU/SPUSubtarget.h | 3 +- lib/Target/MBlaze/MBlazeSubtarget.h | 3 +- lib/Target/Mips/MipsSubtarget.h | 3 +- lib/Target/PowerPC/PPCSubtarget.h | 5 +- lib/Target/SubtargetFeature.cpp | 384 ------------------------ lib/Target/TargetInstrInfo.cpp | 2 +- tools/llc/llc.cpp | 2 +- tools/llvm-mc/llvm-mc.cpp | 2 +- tools/lto/LTOCodeGenerator.cpp | 2 +- tools/lto/LTOModule.cpp | 2 +- utils/TableGen/SubtargetEmitter.cpp | 4 +- utils/TableGen/SubtargetEmitter.h | 2 +- 26 files changed, 787 insertions(+), 791 deletions(-) create mode 100644 include/llvm/MC/MCInstrItineraries.h create mode 100644 include/llvm/MC/SubtargetFeature.h delete mode 100644 include/llvm/Target/SubtargetFeature.h delete mode 100644 include/llvm/Target/TargetInstrItineraries.h create mode 100644 lib/MC/SubtargetFeature.cpp delete mode 100644 lib/Target/SubtargetFeature.cpp diff --git a/include/llvm/MC/MCInstrItineraries.h b/include/llvm/MC/MCInstrItineraries.h new file mode 100644 index 0000000..e942892 --- /dev/null +++ b/include/llvm/MC/MCInstrItineraries.h @@ -0,0 +1,253 @@ +//===-- llvm/MC/MCInstrItineraries.h - Scheduling ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes the structures used for instruction +// itineraries, stages, and operand reads/writes. This is used by +// schedulers to determine instruction stages and latencies. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCINSTRITINERARIES_H +#define LLVM_MC_MCINSTRITINERARIES_H + +#include + +namespace llvm { + +//===----------------------------------------------------------------------===// +/// Instruction stage - These values represent a non-pipelined step in +/// the execution of an instruction. Cycles represents the number of +/// discrete time slots needed to complete the stage. Units represent +/// the choice of functional units that can be used to complete the +/// stage. Eg. IntUnit1, IntUnit2. NextCycles indicates how many +/// cycles should elapse from the start of this stage to the start of +/// the next stage in the itinerary. A value of -1 indicates that the +/// next stage should start immediately after the current one. +/// For example: +/// +/// { 1, x, -1 } +/// indicates that the stage occupies FU x for 1 cycle and that +/// the next stage starts immediately after this one. +/// +/// { 2, x|y, 1 } +/// indicates that the stage occupies either FU x or FU y for 2 +/// consecuative cycles and that the next stage starts one cycle +/// after this stage starts. That is, the stage requirements +/// overlap in time. +/// +/// { 1, x, 0 } +/// indicates that the stage occupies FU x for 1 cycle and that +/// the next stage starts in this same cycle. This can be used to +/// indicate that the instruction requires multiple stages at the +/// same time. +/// +/// FU reservation can be of two different kinds: +/// - FUs which instruction actually requires +/// - FUs which instruction just reserves. Reserved unit is not available for +/// execution of other instruction. However, several instructions can reserve +/// the same unit several times. +/// Such two types of units reservation is used to model instruction domain +/// change stalls, FUs using the same resource (e.g. same register file), etc. + +struct InstrStage { + enum ReservationKinds { + Required = 0, + Reserved = 1 + }; + + unsigned Cycles_; ///< Length of stage in machine cycles + unsigned Units_; ///< Choice of functional units + int NextCycles_; ///< Number of machine cycles to next stage + ReservationKinds Kind_; ///< Kind of the FU reservation + + /// getCycles - returns the number of cycles the stage is occupied + unsigned getCycles() const { + return Cycles_; + } + + /// getUnits - returns the choice of FUs + unsigned getUnits() const { + return Units_; + } + + ReservationKinds getReservationKind() const { + return Kind_; + } + + /// getNextCycles - returns the number of cycles from the start of + /// this stage to the start of the next stage in the itinerary + unsigned getNextCycles() const { + return (NextCycles_ >= 0) ? (unsigned)NextCycles_ : Cycles_; + } +}; + + +//===----------------------------------------------------------------------===// +/// Instruction itinerary - An itinerary represents the scheduling +/// information for an instruction. This includes a set of stages +/// occupies by the instruction, and the pipeline cycle in which +/// operands are read and written. +/// +struct InstrItinerary { + unsigned NumMicroOps; ///< # of micro-ops, 0 means it's variable + unsigned FirstStage; ///< Index of first stage in itinerary + unsigned LastStage; ///< Index of last + 1 stage in itinerary + unsigned FirstOperandCycle; ///< Index of first operand rd/wr + unsigned LastOperandCycle; ///< Index of last + 1 operand rd/wr +}; + + +//===----------------------------------------------------------------------===// +/// Instruction itinerary Data - Itinerary data supplied by a subtarget to be +/// used by a target. +/// +class InstrItineraryData { +public: + const InstrStage *Stages; ///< Array of stages selected + const unsigned *OperandCycles; ///< Array of operand cycles selected + const unsigned *Forwardings; ///< Array of pipeline forwarding pathes + const InstrItinerary *Itineraries; ///< Array of itineraries selected + unsigned IssueWidth; ///< Max issue per cycle. 0=Unknown. + + /// Ctors. + /// + InstrItineraryData() : Stages(0), OperandCycles(0), Forwardings(0), + Itineraries(0), IssueWidth(0) {} + + InstrItineraryData(const InstrStage *S, const unsigned *OS, + const unsigned *F, const InstrItinerary *I) + : Stages(S), OperandCycles(OS), Forwardings(F), Itineraries(I), + IssueWidth(0) {} + + /// isEmpty - Returns true if there are no itineraries. + /// + bool isEmpty() const { return Itineraries == 0; } + + /// isEndMarker - Returns true if the index is for the end marker + /// itinerary. + /// + bool isEndMarker(unsigned ItinClassIndx) const { + return ((Itineraries[ItinClassIndx].FirstStage == ~0U) && + (Itineraries[ItinClassIndx].LastStage == ~0U)); + } + + /// beginStage - Return the first stage of the itinerary. + /// + const InstrStage *beginStage(unsigned ItinClassIndx) const { + unsigned StageIdx = Itineraries[ItinClassIndx].FirstStage; + return Stages + StageIdx; + } + + /// endStage - Return the last+1 stage of the itinerary. + /// + const InstrStage *endStage(unsigned ItinClassIndx) const { + unsigned StageIdx = Itineraries[ItinClassIndx].LastStage; + return Stages + StageIdx; + } + + /// getStageLatency - Return the total stage latency of the given + /// class. The latency is the maximum completion time for any stage + /// in the itinerary. + /// + unsigned getStageLatency(unsigned ItinClassIndx) const { + // If the target doesn't provide itinerary information, use a simple + // non-zero default value for all instructions. Some target's provide a + // dummy (Generic) itinerary which should be handled as if it's itinerary is + // empty. We identify this by looking for a reference to stage zero (invalid + // stage). This is different from beginStage == endState != 0, which could + // be used for zero-latency pseudo ops. + if (isEmpty() || Itineraries[ItinClassIndx].FirstStage == 0) + return 1; + + // Calculate the maximum completion time for any stage. + unsigned Latency = 0, StartCycle = 0; + for (const InstrStage *IS = beginStage(ItinClassIndx), + *E = endStage(ItinClassIndx); IS != E; ++IS) { + Latency = std::max(Latency, StartCycle + IS->getCycles()); + StartCycle += IS->getNextCycles(); + } + + return Latency; + } + + /// getOperandCycle - Return the cycle for the given class and + /// operand. Return -1 if no cycle is specified for the operand. + /// + int getOperandCycle(unsigned ItinClassIndx, unsigned OperandIdx) const { + if (isEmpty()) + return -1; + + unsigned FirstIdx = Itineraries[ItinClassIndx].FirstOperandCycle; + unsigned LastIdx = Itineraries[ItinClassIndx].LastOperandCycle; + if ((FirstIdx + OperandIdx) >= LastIdx) + return -1; + + return (int)OperandCycles[FirstIdx + OperandIdx]; + } + + /// hasPipelineForwarding - Return true if there is a pipeline forwarding + /// between instructions of itinerary classes DefClass and UseClasses so that + /// value produced by an instruction of itinerary class DefClass, operand + /// index DefIdx can be bypassed when it's read by an instruction of + /// itinerary class UseClass, operand index UseIdx. + bool hasPipelineForwarding(unsigned DefClass, unsigned DefIdx, + unsigned UseClass, unsigned UseIdx) const { + unsigned FirstDefIdx = Itineraries[DefClass].FirstOperandCycle; + unsigned LastDefIdx = Itineraries[DefClass].LastOperandCycle; + if ((FirstDefIdx + DefIdx) >= LastDefIdx) + return false; + if (Forwardings[FirstDefIdx + DefIdx] == 0) + return false; + + unsigned FirstUseIdx = Itineraries[UseClass].FirstOperandCycle; + unsigned LastUseIdx = Itineraries[UseClass].LastOperandCycle; + if ((FirstUseIdx + UseIdx) >= LastUseIdx) + return false; + + return Forwardings[FirstDefIdx + DefIdx] == + Forwardings[FirstUseIdx + UseIdx]; + } + + /// getOperandLatency - Compute and return the use operand latency of a given + /// itinerary class and operand index if the value is produced by an + /// instruction of the specified itinerary class and def operand index. + int getOperandLatency(unsigned DefClass, unsigned DefIdx, + unsigned UseClass, unsigned UseIdx) const { + if (isEmpty()) + return -1; + + int DefCycle = getOperandCycle(DefClass, DefIdx); + if (DefCycle == -1) + return -1; + + int UseCycle = getOperandCycle(UseClass, UseIdx); + if (UseCycle == -1) + return -1; + + UseCycle = DefCycle - UseCycle + 1; + if (UseCycle > 0 && + hasPipelineForwarding(DefClass, DefIdx, UseClass, UseIdx)) + // FIXME: This assumes one cycle benefit for every pipeline forwarding. + --UseCycle; + return UseCycle; + } + + /// isMicroCoded - Return true if the instructions in the given class decode + /// to more than one micro-ops. + bool isMicroCoded(unsigned ItinClassIndx) const { + if (isEmpty()) + return false; + return Itineraries[ItinClassIndx].NumMicroOps != 1; + } +}; + + +} // End llvm namespace + +#endif diff --git a/include/llvm/MC/SubtargetFeature.h b/include/llvm/MC/SubtargetFeature.h new file mode 100644 index 0000000..cc56576 --- /dev/null +++ b/include/llvm/MC/SubtargetFeature.h @@ -0,0 +1,118 @@ +//===-- llvm/MC/SubtargetFeature.h - CPU characteristics --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines and manages user or tool specified CPU characteristics. +// The intent is to be able to package specific features that should or should +// not be used on a specific target processor. A tool, such as llc, could, as +// as example, gather chip info from the command line, a long with features +// that should be used on that chip. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_SUBTARGETFEATURE_H +#define LLVM_MC_SUBTARGETFEATURE_H + +#include +#include +#include "llvm/ADT/Triple.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { + class raw_ostream; + +//===----------------------------------------------------------------------===// +/// +/// SubtargetFeatureKV - Used to provide key value pairs for feature and +/// CPU bit flags. +// +struct SubtargetFeatureKV { + const char *Key; // K-V key string + const char *Desc; // Help descriptor + uint64_t Value; // K-V integer value + uint64_t Implies; // K-V bit mask + + // Compare routine for std binary search + bool operator<(const SubtargetFeatureKV &S) const { + return strcmp(Key, S.Key) < 0; + } +}; + +//===----------------------------------------------------------------------===// +/// +/// SubtargetInfoKV - Used to provide key value pairs for CPU and arbitrary +/// pointers. +// +struct SubtargetInfoKV { + const char *Key; // K-V key string + void *Value; // K-V pointer value + + // Compare routine for std binary search + bool operator<(const SubtargetInfoKV &S) const { + return strcmp(Key, S.Key) < 0; + } +}; + +//===----------------------------------------------------------------------===// +/// +/// SubtargetFeatures - Manages the enabling and disabling of subtarget +/// specific features. Features are encoded as a string of the form +/// "cpu,+attr1,+attr2,-attr3,...,+attrN" +/// A comma separates each feature from the next (all lowercase.) +/// The first feature is always the CPU subtype (eg. pentiumm). If the CPU +/// value is "generic" then the CPU subtype should be generic for the target. +/// Each of the remaining features is prefixed with + or - indicating whether +/// that feature should be enabled or disabled contrary to the cpu +/// specification. +/// + +class SubtargetFeatures { + std::vector Features; // Subtarget features as a vector +public: + explicit SubtargetFeatures(const std::string &Initial = std::string()); + + /// Features string accessors. + std::string getString() const; + void setString(const std::string &Initial); + + /// Set the CPU string. Replaces previous setting. Setting to "" clears CPU. + void setCPU(const std::string &String); + + /// Setting CPU string only if no string is set. + void setCPUIfNone(const std::string &String); + + /// Returns current CPU string. + const std::string & getCPU() const; + + /// Adding Features. + void AddFeature(const std::string &String, bool IsEnabled = true); + + /// Get feature bits. + uint64_t getBits(const SubtargetFeatureKV *CPUTable, + size_t CPUTableSize, + const SubtargetFeatureKV *FeatureTable, + size_t FeatureTableSize); + + /// Get info pointer + void *getInfo(const SubtargetInfoKV *Table, size_t TableSize); + + /// Print feature string. + void print(raw_ostream &OS) const; + + // Dump feature info. + void dump() const; + + /// Retrieve a formatted string of the default features for the specified + /// target triple. + void getDefaultSubtargetFeatures(const std::string &CPU, + const Triple& Triple); +}; + +} // End namespace llvm + +#endif diff --git a/include/llvm/Target/SubtargetFeature.h b/include/llvm/Target/SubtargetFeature.h deleted file mode 100644 index cbd2c3b..0000000 --- a/include/llvm/Target/SubtargetFeature.h +++ /dev/null @@ -1,118 +0,0 @@ -//===-- llvm/Target/SubtargetFeature.h - CPU characteristics ----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines and manages user or tool specified CPU characteristics. -// The intent is to be able to package specific features that should or should -// not be used on a specific target processor. A tool, such as llc, could, as -// as example, gather chip info from the command line, a long with features -// that should be used on that chip. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TARGET_SUBTARGETFEATURE_H -#define LLVM_TARGET_SUBTARGETFEATURE_H - -#include -#include -#include "llvm/ADT/Triple.h" -#include "llvm/Support/DataTypes.h" - -namespace llvm { - class raw_ostream; - -//===----------------------------------------------------------------------===// -/// -/// SubtargetFeatureKV - Used to provide key value pairs for feature and -/// CPU bit flags. -// -struct SubtargetFeatureKV { - const char *Key; // K-V key string - const char *Desc; // Help descriptor - uint64_t Value; // K-V integer value - uint64_t Implies; // K-V bit mask - - // Compare routine for std binary search - bool operator<(const SubtargetFeatureKV &S) const { - return strcmp(Key, S.Key) < 0; - } -}; - -//===----------------------------------------------------------------------===// -/// -/// SubtargetInfoKV - Used to provide key value pairs for CPU and arbitrary -/// pointers. -// -struct SubtargetInfoKV { - const char *Key; // K-V key string - void *Value; // K-V pointer value - - // Compare routine for std binary search - bool operator<(const SubtargetInfoKV &S) const { - return strcmp(Key, S.Key) < 0; - } -}; - -//===----------------------------------------------------------------------===// -/// -/// SubtargetFeatures - Manages the enabling and disabling of subtarget -/// specific features. Features are encoded as a string of the form -/// "cpu,+attr1,+attr2,-attr3,...,+attrN" -/// A comma separates each feature from the next (all lowercase.) -/// The first feature is always the CPU subtype (eg. pentiumm). If the CPU -/// value is "generic" then the CPU subtype should be generic for the target. -/// Each of the remaining features is prefixed with + or - indicating whether -/// that feature should be enabled or disabled contrary to the cpu -/// specification. -/// - -class SubtargetFeatures { - std::vector Features; // Subtarget features as a vector -public: - explicit SubtargetFeatures(const std::string &Initial = std::string()); - - /// Features string accessors. - std::string getString() const; - void setString(const std::string &Initial); - - /// Set the CPU string. Replaces previous setting. Setting to "" clears CPU. - void setCPU(const std::string &String); - - /// Setting CPU string only if no string is set. - void setCPUIfNone(const std::string &String); - - /// Returns current CPU string. - const std::string & getCPU() const; - - /// Adding Features. - void AddFeature(const std::string &String, bool IsEnabled = true); - - /// Get feature bits. - uint64_t getBits(const SubtargetFeatureKV *CPUTable, - size_t CPUTableSize, - const SubtargetFeatureKV *FeatureTable, - size_t FeatureTableSize); - - /// Get info pointer - void *getInfo(const SubtargetInfoKV *Table, size_t TableSize); - - /// Print feature string. - void print(raw_ostream &OS) const; - - // Dump feature info. - void dump() const; - - /// Retrieve a formatted string of the default features for the specified - /// target triple. - void getDefaultSubtargetFeatures(const std::string &CPU, - const Triple& Triple); -}; - -} // End namespace llvm - -#endif diff --git a/include/llvm/Target/TargetInstrItineraries.h b/include/llvm/Target/TargetInstrItineraries.h deleted file mode 100644 index 6011402..0000000 --- a/include/llvm/Target/TargetInstrItineraries.h +++ /dev/null @@ -1,253 +0,0 @@ -//===-- llvm/Target/TargetInstrItineraries.h - Scheduling -------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes the structures used for instruction -// itineraries, stages, and operand reads/writes. This is used by -// schedulers to determine instruction stages and latencies. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TARGET_TARGETINSTRITINERARIES_H -#define LLVM_TARGET_TARGETINSTRITINERARIES_H - -#include - -namespace llvm { - -//===----------------------------------------------------------------------===// -/// Instruction stage - These values represent a non-pipelined step in -/// the execution of an instruction. Cycles represents the number of -/// discrete time slots needed to complete the stage. Units represent -/// the choice of functional units that can be used to complete the -/// stage. Eg. IntUnit1, IntUnit2. NextCycles indicates how many -/// cycles should elapse from the start of this stage to the start of -/// the next stage in the itinerary. A value of -1 indicates that the -/// next stage should start immediately after the current one. -/// For example: -/// -/// { 1, x, -1 } -/// indicates that the stage occupies FU x for 1 cycle and that -/// the next stage starts immediately after this one. -/// -/// { 2, x|y, 1 } -/// indicates that the stage occupies either FU x or FU y for 2 -/// consecuative cycles and that the next stage starts one cycle -/// after this stage starts. That is, the stage requirements -/// overlap in time. -/// -/// { 1, x, 0 } -/// indicates that the stage occupies FU x for 1 cycle and that -/// the next stage starts in this same cycle. This can be used to -/// indicate that the instruction requires multiple stages at the -/// same time. -/// -/// FU reservation can be of two different kinds: -/// - FUs which instruction actually requires -/// - FUs which instruction just reserves. Reserved unit is not available for -/// execution of other instruction. However, several instructions can reserve -/// the same unit several times. -/// Such two types of units reservation is used to model instruction domain -/// change stalls, FUs using the same resource (e.g. same register file), etc. - -struct InstrStage { - enum ReservationKinds { - Required = 0, - Reserved = 1 - }; - - unsigned Cycles_; ///< Length of stage in machine cycles - unsigned Units_; ///< Choice of functional units - int NextCycles_; ///< Number of machine cycles to next stage - ReservationKinds Kind_; ///< Kind of the FU reservation - - /// getCycles - returns the number of cycles the stage is occupied - unsigned getCycles() const { - return Cycles_; - } - - /// getUnits - returns the choice of FUs - unsigned getUnits() const { - return Units_; - } - - ReservationKinds getReservationKind() const { - return Kind_; - } - - /// getNextCycles - returns the number of cycles from the start of - /// this stage to the start of the next stage in the itinerary - unsigned getNextCycles() const { - return (NextCycles_ >= 0) ? (unsigned)NextCycles_ : Cycles_; - } -}; - - -//===----------------------------------------------------------------------===// -/// Instruction itinerary - An itinerary represents the scheduling -/// information for an instruction. This includes a set of stages -/// occupies by the instruction, and the pipeline cycle in which -/// operands are read and written. -/// -struct InstrItinerary { - unsigned NumMicroOps; ///< # of micro-ops, 0 means it's variable - unsigned FirstStage; ///< Index of first stage in itinerary - unsigned LastStage; ///< Index of last + 1 stage in itinerary - unsigned FirstOperandCycle; ///< Index of first operand rd/wr - unsigned LastOperandCycle; ///< Index of last + 1 operand rd/wr -}; - - -//===----------------------------------------------------------------------===// -/// Instruction itinerary Data - Itinerary data supplied by a subtarget to be -/// used by a target. -/// -class InstrItineraryData { -public: - const InstrStage *Stages; ///< Array of stages selected - const unsigned *OperandCycles; ///< Array of operand cycles selected - const unsigned *Forwardings; ///< Array of pipeline forwarding pathes - const InstrItinerary *Itineraries; ///< Array of itineraries selected - unsigned IssueWidth; ///< Max issue per cycle. 0=Unknown. - - /// Ctors. - /// - InstrItineraryData() : Stages(0), OperandCycles(0), Forwardings(0), - Itineraries(0), IssueWidth(0) {} - - InstrItineraryData(const InstrStage *S, const unsigned *OS, - const unsigned *F, const InstrItinerary *I) - : Stages(S), OperandCycles(OS), Forwardings(F), Itineraries(I), - IssueWidth(0) {} - - /// isEmpty - Returns true if there are no itineraries. - /// - bool isEmpty() const { return Itineraries == 0; } - - /// isEndMarker - Returns true if the index is for the end marker - /// itinerary. - /// - bool isEndMarker(unsigned ItinClassIndx) const { - return ((Itineraries[ItinClassIndx].FirstStage == ~0U) && - (Itineraries[ItinClassIndx].LastStage == ~0U)); - } - - /// beginStage - Return the first stage of the itinerary. - /// - const InstrStage *beginStage(unsigned ItinClassIndx) const { - unsigned StageIdx = Itineraries[ItinClassIndx].FirstStage; - return Stages + StageIdx; - } - - /// endStage - Return the last+1 stage of the itinerary. - /// - const InstrStage *endStage(unsigned ItinClassIndx) const { - unsigned StageIdx = Itineraries[ItinClassIndx].LastStage; - return Stages + StageIdx; - } - - /// getStageLatency - Return the total stage latency of the given - /// class. The latency is the maximum completion time for any stage - /// in the itinerary. - /// - unsigned getStageLatency(unsigned ItinClassIndx) const { - // If the target doesn't provide itinerary information, use a simple - // non-zero default value for all instructions. Some target's provide a - // dummy (Generic) itinerary which should be handled as if it's itinerary is - // empty. We identify this by looking for a reference to stage zero (invalid - // stage). This is different from beginStage == endState != 0, which could - // be used for zero-latency pseudo ops. - if (isEmpty() || Itineraries[ItinClassIndx].FirstStage == 0) - return 1; - - // Calculate the maximum completion time for any stage. - unsigned Latency = 0, StartCycle = 0; - for (const InstrStage *IS = beginStage(ItinClassIndx), - *E = endStage(ItinClassIndx); IS != E; ++IS) { - Latency = std::max(Latency, StartCycle + IS->getCycles()); - StartCycle += IS->getNextCycles(); - } - - return Latency; - } - - /// getOperandCycle - Return the cycle for the given class and - /// operand. Return -1 if no cycle is specified for the operand. - /// - int getOperandCycle(unsigned ItinClassIndx, unsigned OperandIdx) const { - if (isEmpty()) - return -1; - - unsigned FirstIdx = Itineraries[ItinClassIndx].FirstOperandCycle; - unsigned LastIdx = Itineraries[ItinClassIndx].LastOperandCycle; - if ((FirstIdx + OperandIdx) >= LastIdx) - return -1; - - return (int)OperandCycles[FirstIdx + OperandIdx]; - } - - /// hasPipelineForwarding - Return true if there is a pipeline forwarding - /// between instructions of itinerary classes DefClass and UseClasses so that - /// value produced by an instruction of itinerary class DefClass, operand - /// index DefIdx can be bypassed when it's read by an instruction of - /// itinerary class UseClass, operand index UseIdx. - bool hasPipelineForwarding(unsigned DefClass, unsigned DefIdx, - unsigned UseClass, unsigned UseIdx) const { - unsigned FirstDefIdx = Itineraries[DefClass].FirstOperandCycle; - unsigned LastDefIdx = Itineraries[DefClass].LastOperandCycle; - if ((FirstDefIdx + DefIdx) >= LastDefIdx) - return false; - if (Forwardings[FirstDefIdx + DefIdx] == 0) - return false; - - unsigned FirstUseIdx = Itineraries[UseClass].FirstOperandCycle; - unsigned LastUseIdx = Itineraries[UseClass].LastOperandCycle; - if ((FirstUseIdx + UseIdx) >= LastUseIdx) - return false; - - return Forwardings[FirstDefIdx + DefIdx] == - Forwardings[FirstUseIdx + UseIdx]; - } - - /// getOperandLatency - Compute and return the use operand latency of a given - /// itinerary class and operand index if the value is produced by an - /// instruction of the specified itinerary class and def operand index. - int getOperandLatency(unsigned DefClass, unsigned DefIdx, - unsigned UseClass, unsigned UseIdx) const { - if (isEmpty()) - return -1; - - int DefCycle = getOperandCycle(DefClass, DefIdx); - if (DefCycle == -1) - return -1; - - int UseCycle = getOperandCycle(UseClass, UseIdx); - if (UseCycle == -1) - return -1; - - UseCycle = DefCycle - UseCycle + 1; - if (UseCycle > 0 && - hasPipelineForwarding(DefClass, DefIdx, UseClass, UseIdx)) - // FIXME: This assumes one cycle benefit for every pipeline forwarding. - --UseCycle; - return UseCycle; - } - - /// isMicroCoded - Return true if the instructions in the given class decode - /// to more than one micro-ops. - bool isMicroCoded(unsigned ItinClassIndx) const { - if (isEmpty()) - return false; - return Itineraries[ItinClassIndx].NumMicroOps != 1; - } -}; - - -} // End llvm namespace - -#endif diff --git a/include/llvm/Target/TargetMachine.h b/include/llvm/Target/TargetMachine.h index 78f770c..6544ce2 100644 --- a/include/llvm/Target/TargetMachine.h +++ b/include/llvm/Target/TargetMachine.h @@ -14,29 +14,29 @@ #ifndef LLVM_TARGET_TARGETMACHINE_H #define LLVM_TARGET_TARGETMACHINE_H -#include "llvm/Target/TargetInstrItineraries.h" #include #include namespace llvm { -class Target; +class InstrItineraryData; +class JITCodeEmitter; class MCAsmInfo; +class MCContext; +class Pass; +class PassManager; +class PassManagerBase; +class Target; class TargetData; -class TargetSubtarget; +class TargetELFWriterInfo; +class TargetFrameLowering; class TargetInstrInfo; class TargetIntrinsicInfo; class TargetJITInfo; class TargetLowering; -class TargetSelectionDAGInfo; -class TargetFrameLowering; -class JITCodeEmitter; -class MCContext; class TargetRegisterInfo; -class PassManagerBase; -class PassManager; -class Pass; -class TargetELFWriterInfo; +class TargetSelectionDAGInfo; +class TargetSubtarget; class formatted_raw_ostream; class raw_ostream; diff --git a/lib/CodeGen/IfConversion.cpp b/lib/CodeGen/IfConversion.cpp index d8355ab..c918bf6 100644 --- a/lib/CodeGen/IfConversion.cpp +++ b/lib/CodeGen/IfConversion.cpp @@ -18,8 +18,8 @@ #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/MC/MCInstrItineraries.h" #include "llvm/Target/TargetInstrInfo.h" -#include "llvm/Target/TargetInstrItineraries.h" #include "llvm/Target/TargetLowering.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetRegisterInfo.h" diff --git a/lib/CodeGen/MachineLICM.cpp b/lib/CodeGen/MachineLICM.cpp index 28a81e1..722ceb2 100644 --- a/lib/CodeGen/MachineLICM.cpp +++ b/lib/CodeGen/MachineLICM.cpp @@ -28,10 +28,10 @@ #include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/MC/MCInstrItineraries.h" #include "llvm/Target/TargetLowering.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetInstrInfo.h" -#include "llvm/Target/TargetInstrItineraries.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/ADT/DenseMap.h" diff --git a/lib/CodeGen/ScheduleDAGInstrs.cpp b/lib/CodeGen/ScheduleDAGInstrs.cpp index 94941ec..9cceb4e 100644 --- a/lib/CodeGen/ScheduleDAGInstrs.cpp +++ b/lib/CodeGen/ScheduleDAGInstrs.cpp @@ -21,6 +21,7 @@ #include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/MC/MCInstrItineraries.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetRegisterInfo.h" diff --git a/lib/CodeGen/ScoreboardHazardRecognizer.cpp b/lib/CodeGen/ScoreboardHazardRecognizer.cpp index 35e48cd..0e005d3 100644 --- a/lib/CodeGen/ScoreboardHazardRecognizer.cpp +++ b/lib/CodeGen/ScoreboardHazardRecognizer.cpp @@ -16,11 +16,11 @@ #define DEBUG_TYPE ::llvm::ScoreboardHazardRecognizer::DebugType #include "llvm/CodeGen/ScoreboardHazardRecognizer.h" #include "llvm/CodeGen/ScheduleDAG.h" +#include "llvm/MC/MCInstrItineraries.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetInstrInfo.h" -#include "llvm/Target/TargetInstrItineraries.h" using namespace llvm; diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp index ca70ada..63ca326 100644 --- a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp +++ b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp @@ -17,6 +17,7 @@ #include "ScheduleDAGSDNodes.h" #include "InstrEmitter.h" #include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/MC/MCInstrItineraries.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetLowering.h" diff --git a/lib/ExecutionEngine/TargetSelect.cpp b/lib/ExecutionEngine/TargetSelect.cpp index a8822e5..83b1f05 100644 --- a/lib/ExecutionEngine/TargetSelect.cpp +++ b/lib/ExecutionEngine/TargetSelect.cpp @@ -16,10 +16,10 @@ #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/Module.h" #include "llvm/ADT/Triple.h" +#include "llvm/MC/SubtargetFeature.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/Host.h" -#include "llvm/Target/SubtargetFeature.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetRegistry.h" using namespace llvm; diff --git a/lib/MC/SubtargetFeature.cpp b/lib/MC/SubtargetFeature.cpp new file mode 100644 index 0000000..3ed122a --- /dev/null +++ b/lib/MC/SubtargetFeature.cpp @@ -0,0 +1,384 @@ +//===- SubtargetFeature.cpp - CPU characteristics Implementation ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the SubtargetFeature interface. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/SubtargetFeature.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/StringExtras.h" +#include +#include +#include +#include +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Static Helper Functions +//===----------------------------------------------------------------------===// + +/// hasFlag - Determine if a feature has a flag; '+' or '-' +/// +static inline bool hasFlag(const std::string &Feature) { + assert(!Feature.empty() && "Empty string"); + // Get first character + char Ch = Feature[0]; + // Check if first character is '+' or '-' flag + return Ch == '+' || Ch =='-'; +} + +/// StripFlag - Return string stripped of flag. +/// +static inline std::string StripFlag(const std::string &Feature) { + return hasFlag(Feature) ? Feature.substr(1) : Feature; +} + +/// isEnabled - Return true if enable flag; '+'. +/// +static inline bool isEnabled(const std::string &Feature) { + assert(!Feature.empty() && "Empty string"); + // Get first character + char Ch = Feature[0]; + // Check if first character is '+' for enabled + return Ch == '+'; +} + +/// PrependFlag - Return a string with a prepended flag; '+' or '-'. +/// +static inline std::string PrependFlag(const std::string &Feature, + bool IsEnabled) { + assert(!Feature.empty() && "Empty string"); + if (hasFlag(Feature)) return Feature; + return std::string(IsEnabled ? "+" : "-") + Feature; +} + +/// Split - Splits a string of comma separated items in to a vector of strings. +/// +static void Split(std::vector &V, const std::string &S) { + // Start at beginning of string. + size_t Pos = 0; + while (true) { + // Find the next comma + size_t Comma = S.find(',', Pos); + // If no comma found then the rest of the string is used + if (Comma == std::string::npos) { + // Add string to vector + V.push_back(S.substr(Pos)); + break; + } + // Otherwise add substring to vector + V.push_back(S.substr(Pos, Comma - Pos)); + // Advance to next item + Pos = Comma + 1; + } +} + +/// Join a vector of strings to a string with a comma separating each element. +/// +static std::string Join(const std::vector &V) { + // Start with empty string. + std::string Result; + // If the vector is not empty + if (!V.empty()) { + // Start with the CPU feature + Result = V[0]; + // For each successive feature + for (size_t i = 1; i < V.size(); i++) { + // Add a comma + Result += ","; + // Add the feature + Result += V[i]; + } + } + // Return the features string + return Result; +} + +/// Adding features. +void SubtargetFeatures::AddFeature(const std::string &String, + bool IsEnabled) { + // Don't add empty features + if (!String.empty()) { + // Convert to lowercase, prepend flag and add to vector + Features.push_back(PrependFlag(LowercaseString(String), IsEnabled)); + } +} + +/// Find KV in array using binary search. +template const T *Find(const std::string &S, const T *A, size_t L) { + // Make the lower bound element we're looking for + T KV; + KV.Key = S.c_str(); + // Determine the end of the array + const T *Hi = A + L; + // Binary search the array + const T *F = std::lower_bound(A, Hi, KV); + // If not found then return NULL + if (F == Hi || std::string(F->Key) != S) return NULL; + // Return the found array item + return F; +} + +/// getLongestEntryLength - Return the length of the longest entry in the table. +/// +static size_t getLongestEntryLength(const SubtargetFeatureKV *Table, + size_t Size) { + size_t MaxLen = 0; + for (size_t i = 0; i < Size; i++) + MaxLen = std::max(MaxLen, std::strlen(Table[i].Key)); + return MaxLen; +} + +/// Display help for feature choices. +/// +static void Help(const SubtargetFeatureKV *CPUTable, size_t CPUTableSize, + const SubtargetFeatureKV *FeatTable, size_t FeatTableSize) { + // Determine the length of the longest CPU and Feature entries. + unsigned MaxCPULen = getLongestEntryLength(CPUTable, CPUTableSize); + unsigned MaxFeatLen = getLongestEntryLength(FeatTable, FeatTableSize); + + // Print the CPU table. + errs() << "Available CPUs for this target:\n\n"; + for (size_t i = 0; i != CPUTableSize; i++) + errs() << " " << CPUTable[i].Key + << std::string(MaxCPULen - std::strlen(CPUTable[i].Key), ' ') + << " - " << CPUTable[i].Desc << ".\n"; + errs() << "\n"; + + // Print the Feature table. + errs() << "Available features for this target:\n\n"; + for (size_t i = 0; i != FeatTableSize; i++) + errs() << " " << FeatTable[i].Key + << std::string(MaxFeatLen - std::strlen(FeatTable[i].Key), ' ') + << " - " << FeatTable[i].Desc << ".\n"; + errs() << "\n"; + + errs() << "Use +feature to enable a feature, or -feature to disable it.\n" + << "For example, llc -mcpu=mycpu -mattr=+feature1,-feature2\n"; + std::exit(1); +} + +//===----------------------------------------------------------------------===// +// SubtargetFeatures Implementation +//===----------------------------------------------------------------------===// + +SubtargetFeatures::SubtargetFeatures(const std::string &Initial) { + // Break up string into separate features + Split(Features, Initial); +} + + +std::string SubtargetFeatures::getString() const { + return Join(Features); +} +void SubtargetFeatures::setString(const std::string &Initial) { + // Throw out old features + Features.clear(); + // Break up string into separate features + Split(Features, LowercaseString(Initial)); +} + + +/// setCPU - Set the CPU string. Replaces previous setting. Setting to "" +/// clears CPU. +void SubtargetFeatures::setCPU(const std::string &String) { + Features[0] = LowercaseString(String); +} + + +/// setCPUIfNone - Setting CPU string only if no string is set. +/// +void SubtargetFeatures::setCPUIfNone(const std::string &String) { + if (Features[0].empty()) setCPU(String); +} + +/// getCPU - Returns current CPU. +/// +const std::string & SubtargetFeatures::getCPU() const { + return Features[0]; +} + + +/// SetImpliedBits - For each feature that is (transitively) implied by this +/// feature, set it. +/// +static +void SetImpliedBits(uint64_t &Bits, const SubtargetFeatureKV *FeatureEntry, + const SubtargetFeatureKV *FeatureTable, + size_t FeatureTableSize) { + for (size_t i = 0; i < FeatureTableSize; ++i) { + const SubtargetFeatureKV &FE = FeatureTable[i]; + + if (FeatureEntry->Value == FE.Value) continue; + + if (FeatureEntry->Implies & FE.Value) { + Bits |= FE.Value; + SetImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize); + } + } +} + +/// ClearImpliedBits - For each feature that (transitively) implies this +/// feature, clear it. +/// +static +void ClearImpliedBits(uint64_t &Bits, const SubtargetFeatureKV *FeatureEntry, + const SubtargetFeatureKV *FeatureTable, + size_t FeatureTableSize) { + for (size_t i = 0; i < FeatureTableSize; ++i) { + const SubtargetFeatureKV &FE = FeatureTable[i]; + + if (FeatureEntry->Value == FE.Value) continue; + + if (FE.Implies & FeatureEntry->Value) { + Bits &= ~FE.Value; + ClearImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize); + } + } +} + +/// getBits - Get feature bits. +/// +uint64_t SubtargetFeatures::getBits(const SubtargetFeatureKV *CPUTable, + size_t CPUTableSize, + const SubtargetFeatureKV *FeatureTable, + size_t FeatureTableSize) { + assert(CPUTable && "missing CPU table"); + assert(FeatureTable && "missing features table"); +#ifndef NDEBUG + for (size_t i = 1; i < CPUTableSize; i++) { + assert(strcmp(CPUTable[i - 1].Key, CPUTable[i].Key) < 0 && + "CPU table is not sorted"); + } + for (size_t i = 1; i < FeatureTableSize; i++) { + assert(strcmp(FeatureTable[i - 1].Key, FeatureTable[i].Key) < 0 && + "CPU features table is not sorted"); + } +#endif + uint64_t Bits = 0; // Resulting bits + + // Check if help is needed + if (Features[0] == "help") + Help(CPUTable, CPUTableSize, FeatureTable, FeatureTableSize); + + // Find CPU entry + const SubtargetFeatureKV *CPUEntry = + Find(Features[0], CPUTable, CPUTableSize); + // If there is a match + if (CPUEntry) { + // Set base feature bits + Bits = CPUEntry->Value; + + // Set the feature implied by this CPU feature, if any. + for (size_t i = 0; i < FeatureTableSize; ++i) { + const SubtargetFeatureKV &FE = FeatureTable[i]; + if (CPUEntry->Value & FE.Value) + SetImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize); + } + } else { + errs() << "'" << Features[0] + << "' is not a recognized processor for this target" + << " (ignoring processor)\n"; + } + // Iterate through each feature + for (size_t i = 1; i < Features.size(); i++) { + const std::string &Feature = Features[i]; + + // Check for help + if (Feature == "+help") + Help(CPUTable, CPUTableSize, FeatureTable, FeatureTableSize); + + // Find feature in table. + const SubtargetFeatureKV *FeatureEntry = + Find(StripFlag(Feature), FeatureTable, FeatureTableSize); + // If there is a match + if (FeatureEntry) { + // Enable/disable feature in bits + if (isEnabled(Feature)) { + Bits |= FeatureEntry->Value; + + // For each feature that this implies, set it. + SetImpliedBits(Bits, FeatureEntry, FeatureTable, FeatureTableSize); + } else { + Bits &= ~FeatureEntry->Value; + + // For each feature that implies this, clear it. + ClearImpliedBits(Bits, FeatureEntry, FeatureTable, FeatureTableSize); + } + } else { + errs() << "'" << Feature + << "' is not a recognized feature for this target" + << " (ignoring feature)\n"; + } + } + + return Bits; +} + +/// Get info pointer +void *SubtargetFeatures::getInfo(const SubtargetInfoKV *Table, + size_t TableSize) { + assert(Table && "missing table"); +#ifndef NDEBUG + for (size_t i = 1; i < TableSize; i++) { + assert(strcmp(Table[i - 1].Key, Table[i].Key) < 0 && "Table is not sorted"); + } +#endif + + // Find entry + const SubtargetInfoKV *Entry = Find(Features[0], Table, TableSize); + + if (Entry) { + return Entry->Value; + } else { + errs() << "'" << Features[0] + << "' is not a recognized processor for this target" + << " (ignoring processor)\n"; + return NULL; + } +} + +/// print - Print feature string. +/// +void SubtargetFeatures::print(raw_ostream &OS) const { + for (size_t i = 0, e = Features.size(); i != e; ++i) + OS << Features[i] << " "; + OS << "\n"; +} + +/// dump - Dump feature info. +/// +void SubtargetFeatures::dump() const { + print(dbgs()); +} + +/// getDefaultSubtargetFeatures - Return a string listing the features +/// associated with the target triple. +/// +/// FIXME: This is an inelegant way of specifying the features of a +/// subtarget. It would be better if we could encode this information +/// into the IR. See . +/// +void SubtargetFeatures::getDefaultSubtargetFeatures(const std::string &CPU, + const Triple& Triple) { + setCPU(CPU); + + if (Triple.getVendor() == Triple::Apple) { + if (Triple.getArch() == Triple::ppc) { + // powerpc-apple-* + AddFeature("altivec"); + } else if (Triple.getArch() == Triple::ppc64) { + // powerpc64-apple-* + AddFeature("64bit"); + AddFeature("altivec"); + } + } +} diff --git a/lib/Target/ARM/ARMSubtarget.h b/lib/Target/ARM/ARMSubtarget.h index 0271c87..e4bcf3e 100644 --- a/lib/Target/ARM/ARMSubtarget.h +++ b/lib/Target/ARM/ARMSubtarget.h @@ -14,9 +14,8 @@ #ifndef ARMSUBTARGET_H #define ARMSUBTARGET_H -#include "llvm/Target/TargetInstrItineraries.h" -#include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetSubtarget.h" +#include "llvm/MC/MCInstrItineraries.h" #include "llvm/ADT/Triple.h" #include diff --git a/lib/Target/Alpha/AlphaSubtarget.h b/lib/Target/Alpha/AlphaSubtarget.h index f0eb93c..ab7d1e0 100644 --- a/lib/Target/Alpha/AlphaSubtarget.h +++ b/lib/Target/Alpha/AlphaSubtarget.h @@ -14,9 +14,8 @@ #ifndef ALPHASUBTARGET_H #define ALPHASUBTARGET_H -#include "llvm/Target/TargetInstrItineraries.h" #include "llvm/Target/TargetSubtarget.h" - +#include "llvm/MC/MCInstrItineraries.h" #include namespace llvm { diff --git a/lib/Target/CellSPU/SPUSubtarget.h b/lib/Target/CellSPU/SPUSubtarget.h index d792930..39b2d86 100644 --- a/lib/Target/CellSPU/SPUSubtarget.h +++ b/lib/Target/CellSPU/SPUSubtarget.h @@ -14,9 +14,8 @@ #ifndef CELLSUBTARGET_H #define CELLSUBTARGET_H -#include "llvm/Target/TargetInstrItineraries.h" #include "llvm/Target/TargetSubtarget.h" - +#include "llvm/MC/MCInstrItineraries.h" #include namespace llvm { diff --git a/lib/Target/MBlaze/MBlazeSubtarget.h b/lib/Target/MBlaze/MBlazeSubtarget.h index 2255b28..342b2fb 100644 --- a/lib/Target/MBlaze/MBlazeSubtarget.h +++ b/lib/Target/MBlaze/MBlazeSubtarget.h @@ -15,8 +15,7 @@ #define MBLAZESUBTARGET_H #include "llvm/Target/TargetSubtarget.h" -#include "llvm/Target/TargetMachine.h" - +#include "llvm/MC/MCInstrItineraries.h" #include namespace llvm { diff --git a/lib/Target/Mips/MipsSubtarget.h b/lib/Target/Mips/MipsSubtarget.h index 096bbed..f09df6b 100644 --- a/lib/Target/Mips/MipsSubtarget.h +++ b/lib/Target/Mips/MipsSubtarget.h @@ -15,8 +15,7 @@ #define MIPSSUBTARGET_H #include "llvm/Target/TargetSubtarget.h" -#include "llvm/Target/TargetMachine.h" - +#include "llvm/MC/MCInstrItineraries.h" #include namespace llvm { diff --git a/lib/Target/PowerPC/PPCSubtarget.h b/lib/Target/PowerPC/PPCSubtarget.h index 8fd1a44..799bb3d 100644 --- a/lib/Target/PowerPC/PPCSubtarget.h +++ b/lib/Target/PowerPC/PPCSubtarget.h @@ -14,10 +14,9 @@ #ifndef POWERPCSUBTARGET_H #define POWERPCSUBTARGET_H -#include "llvm/ADT/Triple.h" -#include "llvm/Target/TargetInstrItineraries.h" #include "llvm/Target/TargetSubtarget.h" - +#include "llvm/MC/MCInstrItineraries.h" +#include "llvm/ADT/Triple.h" #include // GCC #defines PPC on Linux but we use it as our namespace name diff --git a/lib/Target/SubtargetFeature.cpp b/lib/Target/SubtargetFeature.cpp deleted file mode 100644 index e0a9de8..0000000 --- a/lib/Target/SubtargetFeature.cpp +++ /dev/null @@ -1,384 +0,0 @@ -//===- SubtargetFeature.cpp - CPU characteristics Implementation ----------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the SubtargetFeature interface. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Target/SubtargetFeature.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/ADT/StringExtras.h" -#include -#include -#include -#include -using namespace llvm; - -//===----------------------------------------------------------------------===// -// Static Helper Functions -//===----------------------------------------------------------------------===// - -/// hasFlag - Determine if a feature has a flag; '+' or '-' -/// -static inline bool hasFlag(const std::string &Feature) { - assert(!Feature.empty() && "Empty string"); - // Get first character - char Ch = Feature[0]; - // Check if first character is '+' or '-' flag - return Ch == '+' || Ch =='-'; -} - -/// StripFlag - Return string stripped of flag. -/// -static inline std::string StripFlag(const std::string &Feature) { - return hasFlag(Feature) ? Feature.substr(1) : Feature; -} - -/// isEnabled - Return true if enable flag; '+'. -/// -static inline bool isEnabled(const std::string &Feature) { - assert(!Feature.empty() && "Empty string"); - // Get first character - char Ch = Feature[0]; - // Check if first character is '+' for enabled - return Ch == '+'; -} - -/// PrependFlag - Return a string with a prepended flag; '+' or '-'. -/// -static inline std::string PrependFlag(const std::string &Feature, - bool IsEnabled) { - assert(!Feature.empty() && "Empty string"); - if (hasFlag(Feature)) return Feature; - return std::string(IsEnabled ? "+" : "-") + Feature; -} - -/// Split - Splits a string of comma separated items in to a vector of strings. -/// -static void Split(std::vector &V, const std::string &S) { - // Start at beginning of string. - size_t Pos = 0; - while (true) { - // Find the next comma - size_t Comma = S.find(',', Pos); - // If no comma found then the rest of the string is used - if (Comma == std::string::npos) { - // Add string to vector - V.push_back(S.substr(Pos)); - break; - } - // Otherwise add substring to vector - V.push_back(S.substr(Pos, Comma - Pos)); - // Advance to next item - Pos = Comma + 1; - } -} - -/// Join a vector of strings to a string with a comma separating each element. -/// -static std::string Join(const std::vector &V) { - // Start with empty string. - std::string Result; - // If the vector is not empty - if (!V.empty()) { - // Start with the CPU feature - Result = V[0]; - // For each successive feature - for (size_t i = 1; i < V.size(); i++) { - // Add a comma - Result += ","; - // Add the feature - Result += V[i]; - } - } - // Return the features string - return Result; -} - -/// Adding features. -void SubtargetFeatures::AddFeature(const std::string &String, - bool IsEnabled) { - // Don't add empty features - if (!String.empty()) { - // Convert to lowercase, prepend flag and add to vector - Features.push_back(PrependFlag(LowercaseString(String), IsEnabled)); - } -} - -/// Find KV in array using binary search. -template const T *Find(const std::string &S, const T *A, size_t L) { - // Make the lower bound element we're looking for - T KV; - KV.Key = S.c_str(); - // Determine the end of the array - const T *Hi = A + L; - // Binary search the array - const T *F = std::lower_bound(A, Hi, KV); - // If not found then return NULL - if (F == Hi || std::string(F->Key) != S) return NULL; - // Return the found array item - return F; -} - -/// getLongestEntryLength - Return the length of the longest entry in the table. -/// -static size_t getLongestEntryLength(const SubtargetFeatureKV *Table, - size_t Size) { - size_t MaxLen = 0; - for (size_t i = 0; i < Size; i++) - MaxLen = std::max(MaxLen, std::strlen(Table[i].Key)); - return MaxLen; -} - -/// Display help for feature choices. -/// -static void Help(const SubtargetFeatureKV *CPUTable, size_t CPUTableSize, - const SubtargetFeatureKV *FeatTable, size_t FeatTableSize) { - // Determine the length of the longest CPU and Feature entries. - unsigned MaxCPULen = getLongestEntryLength(CPUTable, CPUTableSize); - unsigned MaxFeatLen = getLongestEntryLength(FeatTable, FeatTableSize); - - // Print the CPU table. - errs() << "Available CPUs for this target:\n\n"; - for (size_t i = 0; i != CPUTableSize; i++) - errs() << " " << CPUTable[i].Key - << std::string(MaxCPULen - std::strlen(CPUTable[i].Key), ' ') - << " - " << CPUTable[i].Desc << ".\n"; - errs() << "\n"; - - // Print the Feature table. - errs() << "Available features for this target:\n\n"; - for (size_t i = 0; i != FeatTableSize; i++) - errs() << " " << FeatTable[i].Key - << std::string(MaxFeatLen - std::strlen(FeatTable[i].Key), ' ') - << " - " << FeatTable[i].Desc << ".\n"; - errs() << "\n"; - - errs() << "Use +feature to enable a feature, or -feature to disable it.\n" - << "For example, llc -mcpu=mycpu -mattr=+feature1,-feature2\n"; - std::exit(1); -} - -//===----------------------------------------------------------------------===// -// SubtargetFeatures Implementation -//===----------------------------------------------------------------------===// - -SubtargetFeatures::SubtargetFeatures(const std::string &Initial) { - // Break up string into separate features - Split(Features, Initial); -} - - -std::string SubtargetFeatures::getString() const { - return Join(Features); -} -void SubtargetFeatures::setString(const std::string &Initial) { - // Throw out old features - Features.clear(); - // Break up string into separate features - Split(Features, LowercaseString(Initial)); -} - - -/// setCPU - Set the CPU string. Replaces previous setting. Setting to "" -/// clears CPU. -void SubtargetFeatures::setCPU(const std::string &String) { - Features[0] = LowercaseString(String); -} - - -/// setCPUIfNone - Setting CPU string only if no string is set. -/// -void SubtargetFeatures::setCPUIfNone(const std::string &String) { - if (Features[0].empty()) setCPU(String); -} - -/// getCPU - Returns current CPU. -/// -const std::string & SubtargetFeatures::getCPU() const { - return Features[0]; -} - - -/// SetImpliedBits - For each feature that is (transitively) implied by this -/// feature, set it. -/// -static -void SetImpliedBits(uint64_t &Bits, const SubtargetFeatureKV *FeatureEntry, - const SubtargetFeatureKV *FeatureTable, - size_t FeatureTableSize) { - for (size_t i = 0; i < FeatureTableSize; ++i) { - const SubtargetFeatureKV &FE = FeatureTable[i]; - - if (FeatureEntry->Value == FE.Value) continue; - - if (FeatureEntry->Implies & FE.Value) { - Bits |= FE.Value; - SetImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize); - } - } -} - -/// ClearImpliedBits - For each feature that (transitively) implies this -/// feature, clear it. -/// -static -void ClearImpliedBits(uint64_t &Bits, const SubtargetFeatureKV *FeatureEntry, - const SubtargetFeatureKV *FeatureTable, - size_t FeatureTableSize) { - for (size_t i = 0; i < FeatureTableSize; ++i) { - const SubtargetFeatureKV &FE = FeatureTable[i]; - - if (FeatureEntry->Value == FE.Value) continue; - - if (FE.Implies & FeatureEntry->Value) { - Bits &= ~FE.Value; - ClearImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize); - } - } -} - -/// getBits - Get feature bits. -/// -uint64_t SubtargetFeatures::getBits(const SubtargetFeatureKV *CPUTable, - size_t CPUTableSize, - const SubtargetFeatureKV *FeatureTable, - size_t FeatureTableSize) { - assert(CPUTable && "missing CPU table"); - assert(FeatureTable && "missing features table"); -#ifndef NDEBUG - for (size_t i = 1; i < CPUTableSize; i++) { - assert(strcmp(CPUTable[i - 1].Key, CPUTable[i].Key) < 0 && - "CPU table is not sorted"); - } - for (size_t i = 1; i < FeatureTableSize; i++) { - assert(strcmp(FeatureTable[i - 1].Key, FeatureTable[i].Key) < 0 && - "CPU features table is not sorted"); - } -#endif - uint64_t Bits = 0; // Resulting bits - - // Check if help is needed - if (Features[0] == "help") - Help(CPUTable, CPUTableSize, FeatureTable, FeatureTableSize); - - // Find CPU entry - const SubtargetFeatureKV *CPUEntry = - Find(Features[0], CPUTable, CPUTableSize); - // If there is a match - if (CPUEntry) { - // Set base feature bits - Bits = CPUEntry->Value; - - // Set the feature implied by this CPU feature, if any. - for (size_t i = 0; i < FeatureTableSize; ++i) { - const SubtargetFeatureKV &FE = FeatureTable[i]; - if (CPUEntry->Value & FE.Value) - SetImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize); - } - } else { - errs() << "'" << Features[0] - << "' is not a recognized processor for this target" - << " (ignoring processor)\n"; - } - // Iterate through each feature - for (size_t i = 1; i < Features.size(); i++) { - const std::string &Feature = Features[i]; - - // Check for help - if (Feature == "+help") - Help(CPUTable, CPUTableSize, FeatureTable, FeatureTableSize); - - // Find feature in table. - const SubtargetFeatureKV *FeatureEntry = - Find(StripFlag(Feature), FeatureTable, FeatureTableSize); - // If there is a match - if (FeatureEntry) { - // Enable/disable feature in bits - if (isEnabled(Feature)) { - Bits |= FeatureEntry->Value; - - // For each feature that this implies, set it. - SetImpliedBits(Bits, FeatureEntry, FeatureTable, FeatureTableSize); - } else { - Bits &= ~FeatureEntry->Value; - - // For each feature that implies this, clear it. - ClearImpliedBits(Bits, FeatureEntry, FeatureTable, FeatureTableSize); - } - } else { - errs() << "'" << Feature - << "' is not a recognized feature for this target" - << " (ignoring feature)\n"; - } - } - - return Bits; -} - -/// Get info pointer -void *SubtargetFeatures::getInfo(const SubtargetInfoKV *Table, - size_t TableSize) { - assert(Table && "missing table"); -#ifndef NDEBUG - for (size_t i = 1; i < TableSize; i++) { - assert(strcmp(Table[i - 1].Key, Table[i].Key) < 0 && "Table is not sorted"); - } -#endif - - // Find entry - const SubtargetInfoKV *Entry = Find(Features[0], Table, TableSize); - - if (Entry) { - return Entry->Value; - } else { - errs() << "'" << Features[0] - << "' is not a recognized processor for this target" - << " (ignoring processor)\n"; - return NULL; - } -} - -/// print - Print feature string. -/// -void SubtargetFeatures::print(raw_ostream &OS) const { - for (size_t i = 0, e = Features.size(); i != e; ++i) - OS << Features[i] << " "; - OS << "\n"; -} - -/// dump - Dump feature info. -/// -void SubtargetFeatures::dump() const { - print(dbgs()); -} - -/// getDefaultSubtargetFeatures - Return a string listing the features -/// associated with the target triple. -/// -/// FIXME: This is an inelegant way of specifying the features of a -/// subtarget. It would be better if we could encode this information -/// into the IR. See . -/// -void SubtargetFeatures::getDefaultSubtargetFeatures(const std::string &CPU, - const Triple& Triple) { - setCPU(CPU); - - if (Triple.getVendor() == Triple::Apple) { - if (Triple.getArch() == Triple::ppc) { - // powerpc-apple-* - AddFeature("altivec"); - } else if (Triple.getArch() == Triple::ppc64) { - // powerpc64-apple-* - AddFeature("64bit"); - AddFeature("altivec"); - } - } -} diff --git a/lib/Target/TargetInstrInfo.cpp b/lib/Target/TargetInstrInfo.cpp index d30bb6c..2931416 100644 --- a/lib/Target/TargetInstrInfo.cpp +++ b/lib/Target/TargetInstrInfo.cpp @@ -12,10 +12,10 @@ //===----------------------------------------------------------------------===// #include "llvm/Target/TargetInstrInfo.h" -#include "llvm/Target/TargetInstrItineraries.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/CodeGen/SelectionDAGNodes.h" #include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCInstrItineraries.h" #include "llvm/Support/ErrorHandling.h" #include using namespace llvm; diff --git a/tools/llc/llc.cpp b/tools/llc/llc.cpp index 162d6c8..e89b4d8 100644 --- a/tools/llc/llc.cpp +++ b/tools/llc/llc.cpp @@ -22,6 +22,7 @@ #include "llvm/CodeGen/LinkAllAsmWriterComponents.h" #include "llvm/CodeGen/LinkAllCodegenComponents.h" #include "llvm/Config/config.h" +#include "llvm/MC/SubtargetFeature.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FormattedStream.h" @@ -31,7 +32,6 @@ #include "llvm/Support/ToolOutputFile.h" #include "llvm/Support/Host.h" #include "llvm/Support/Signals.h" -#include "llvm/Target/SubtargetFeature.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetRegistry.h" diff --git a/tools/llvm-mc/llvm-mc.cpp b/tools/llvm-mc/llvm-mc.cpp index 077f0e6..e224459 100644 --- a/tools/llvm-mc/llvm-mc.cpp +++ b/tools/llvm-mc/llvm-mc.cpp @@ -19,11 +19,11 @@ #include "llvm/MC/MCInstPrinter.h" #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCStreamer.h" +#include "llvm/MC/SubtargetFeature.h" #include "llvm/Target/TargetAsmBackend.h" #include "llvm/Target/TargetAsmParser.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetRegistry.h" -#include "llvm/Target/SubtargetFeature.h" // FIXME. #include "llvm/Target/TargetAsmInfo.h" // FIXME. #include "llvm/Target/TargetLowering.h" // FIXME. #include "llvm/Target/TargetLoweringObjectFile.h" // FIXME. diff --git a/tools/lto/LTOCodeGenerator.cpp b/tools/lto/LTOCodeGenerator.cpp index 3abd641..f175255 100644 --- a/tools/lto/LTOCodeGenerator.cpp +++ b/tools/lto/LTOCodeGenerator.cpp @@ -26,8 +26,8 @@ #include "llvm/Bitcode/ReaderWriter.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" +#include "llvm/MC/SubtargetFeature.h" #include "llvm/Target/Mangler.h" -#include "llvm/Target/SubtargetFeature.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetMachine.h" diff --git a/tools/lto/LTOModule.cpp b/tools/lto/LTOModule.cpp index 4e754f6..814d80b 100644 --- a/tools/lto/LTOModule.cpp +++ b/tools/lto/LTOModule.cpp @@ -29,7 +29,6 @@ #include "llvm/Support/SourceMgr.h" #include "llvm/Support/system_error.h" #include "llvm/Target/Mangler.h" -#include "llvm/Target/SubtargetFeature.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" @@ -37,6 +36,7 @@ #include "llvm/MC/MCParser/MCAsmParser.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" +#include "llvm/MC/SubtargetFeature.h" #include "llvm/Target/TargetAsmParser.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetRegistry.h" diff --git a/utils/TableGen/SubtargetEmitter.cpp b/utils/TableGen/SubtargetEmitter.cpp index 928fa4b..6899cb1 100644 --- a/utils/TableGen/SubtargetEmitter.cpp +++ b/utils/TableGen/SubtargetEmitter.cpp @@ -654,8 +654,8 @@ void SubtargetEmitter::run(raw_ostream &OS) { OS << "#include \"llvm/Support/Debug.h\"\n"; OS << "#include \"llvm/Support/raw_ostream.h\"\n"; - OS << "#include \"llvm/Target/SubtargetFeature.h\"\n"; - OS << "#include \"llvm/Target/TargetInstrItineraries.h\"\n\n"; + OS << "#include \"llvm/MC/SubtargetFeature.h\"\n"; + OS << "#include \"llvm/MC/MCInstrItineraries.h\"\n\n"; // Enumeration(OS, "FuncUnit", true); // OS<<"\n"; diff --git a/utils/TableGen/SubtargetEmitter.h b/utils/TableGen/SubtargetEmitter.h index 93055b7..cf793c8 100644 --- a/utils/TableGen/SubtargetEmitter.h +++ b/utils/TableGen/SubtargetEmitter.h @@ -15,7 +15,7 @@ #define SUBTARGET_EMITTER_H #include "TableGenBackend.h" -#include "llvm/Target/TargetInstrItineraries.h" +#include "llvm/MC/MCInstrItineraries.h" #include #include #include -- cgit v1.1 From 2c0cbce763a258ac58590a8ca3c28ff722093fef Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Wed, 29 Jun 2011 02:03:36 +0000 Subject: Revert r134047 while investigating a llvm-gcc-i386-linux-selfhost miscompile. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134053 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/RegAllocGreedy.cpp | 394 ++++++++++++++--------------------------- lib/CodeGen/SplitKit.cpp | 25 +-- lib/CodeGen/SplitKit.h | 10 -- 3 files changed, 138 insertions(+), 291 deletions(-) diff --git a/lib/CodeGen/RegAllocGreedy.cpp b/lib/CodeGen/RegAllocGreedy.cpp index 912d899..d0e6a64 100644 --- a/lib/CodeGen/RegAllocGreedy.cpp +++ b/lib/CodeGen/RegAllocGreedy.cpp @@ -763,46 +763,32 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg, // Create the main cross-block interval. const unsigned MainIntv = SE->openIntv(); - // First handle all the blocks with uses. + // First add all defs that are live out of a block. ArrayRef UseBlocks = SA->getUseBlocks(); for (unsigned i = 0; i != UseBlocks.size(); ++i) { const SplitAnalysis::BlockInfo &BI = UseBlocks[i]; - bool RegIn = BI.LiveIn && - LiveBundles[Bundles->getBundle(BI.MBB->getNumber(), 0)]; - bool RegOut = BI.LiveOut && - LiveBundles[Bundles->getBundle(BI.MBB->getNumber(), 1)]; + bool RegIn = LiveBundles[Bundles->getBundle(BI.MBB->getNumber(), 0)]; + bool RegOut = LiveBundles[Bundles->getBundle(BI.MBB->getNumber(), 1)]; // Create separate intervals for isolated blocks with multiple uses. - // - // |---o---o---| Enter and leave on the stack. - // ____-----____ Create local interval for uses. - // - // | o---o---| Defined in block, leave on stack. - // -----____ Create local interval for uses. - // - // |---o---x | Enter on stack, killed in block. - // ____----- Create local interval for uses. - // - if (!RegIn && !RegOut) { + if (!RegIn && !RegOut && BI.FirstUse != BI.LastUse) { DEBUG(dbgs() << "BB#" << BI.MBB->getNumber() << " isolated.\n"); - if (!BI.isOneInstr()) { - SE->splitSingleBlock(BI); - SE->selectIntv(MainIntv); - } + SE->splitSingleBlock(BI); + SE->selectIntv(MainIntv); continue; } + // Should the register be live out? + if (!BI.LiveOut || !RegOut) + continue; + SlotIndex Start, Stop; tie(Start, Stop) = Indexes->getMBBRange(BI.MBB); Intf.moveToBlock(BI.MBB->getNumber()); - DEBUG(dbgs() << "EB#" << Bundles->getBundle(BI.MBB->getNumber(), 0) - << (RegIn ? " => " : " -- ") - << "BB#" << BI.MBB->getNumber() - << (RegOut ? " => " : " -- ") - << " EB#" << Bundles->getBundle(BI.MBB->getNumber(), 1) + DEBUG(dbgs() << "BB#" << BI.MBB->getNumber() << " -> EB#" + << Bundles->getBundle(BI.MBB->getNumber(), 1) << " [" << Start << ';' << SA->getLastSplitPoint(BI.MBB->getNumber()) << '-' << Stop - << ") uses [" << BI.FirstUse << ';' << BI.LastUse << ") intf [" << Intf.first() << ';' << Intf.last() << ')'); // The interference interval should either be invalid or overlap MBB. @@ -811,266 +797,150 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg, assert((!Intf.hasInterference() || Intf.last() > Start) && "Bad interference"); - // We are now ready to decide where to split in the current block. There - // are many variables guiding the decision: - // - // - RegIn / RegOut: The global splitting algorithm's decisions for our - // ingoing and outgoing bundles. - // - // - BI.BlockIn / BI.BlockOut: Is the live range live-in and/or live-out - // from this block. - // - // - Intf.hasInterference(): Is there interference in this block. - // - // - Intf.first() / Inft.last(): The range of interference. - // - // The live range should be split such that MainIntv is live-in when RegIn - // is set, and live-out when RegOut is set. MainIntv should never overlap - // the interference, and the stack interval should never have more than one - // use per block. - - // No splits can be inserted after LastSplitPoint, overlap instead. - SlotIndex LastSplitPoint = Stop; - if (BI.LiveOut) - LastSplitPoint = SA->getLastSplitPoint(BI.MBB->getNumber()); - - // At this point, we know that either RegIn or RegOut is set. We dealt with - // the all-stack case above. - - // Blocks without interference are relatively easy. + // Check interference leaving the block. if (!Intf.hasInterference()) { - DEBUG(dbgs() << ", no interference.\n"); - SE->selectIntv(MainIntv); - // The easiest case has MainIntv live through. - // - // |---o---o---| Live-in, live-out. - // ============= Use MainIntv everywhere. - // - SlotIndex From = Start, To = Stop; - - // Block entry. Reload before the first use if MainIntv is not live-in. - // - // |---o-- Enter on stack. - // ____=== Reload before first use. - // - // | o-- Defined in block. - // === Use MainIntv from def. - // - if (!RegIn) - From = SE->enterIntvBefore(BI.FirstUse); - - // Block exit. Handle cases where MainIntv is not live-out. - if (!BI.LiveOut) - // - // --x | Killed in block. - // === Use MainIntv up to kill. - // - To = SE->leaveIntvAfter(BI.LastUse); - else if (!RegOut) { - // - // --o---| Live-out on stack. - // ===____ Use MainIntv up to last use, switch to stack. - // - // -----o| Live-out on stack, last use after last split point. - // ====== Extend MainIntv to last use, overlapping. - // \____ Copy to stack interval before last split point. - // - if (BI.LastUse < LastSplitPoint) - To = SE->leaveIntvAfter(BI.LastUse); - else { - // The last use is after the last split point, it is probably an - // indirect branch. - To = SE->leaveIntvBefore(LastSplitPoint); - // Run a double interval from the split to the last use. This makes - // it possible to spill the complement without affecting the indirect - // branch. - SE->overlapIntv(To, BI.LastUse); - } + // Block is interference-free. + DEBUG(dbgs() << ", no interference"); + if (!BI.LiveThrough) { + DEBUG(dbgs() << ", not live-through.\n"); + SE->useIntv(SE->enterIntvBefore(BI.FirstUse), Stop); + continue; } - - // Paint in MainIntv liveness for this block. - SE->useIntv(From, To); + if (!RegIn) { + // Block is live-through, but entry bundle is on the stack. + // Reload just before the first use. + DEBUG(dbgs() << ", not live-in, enter before first use.\n"); + SE->useIntv(SE->enterIntvBefore(BI.FirstUse), Stop); + continue; + } + DEBUG(dbgs() << ", live-through.\n"); continue; } - // We are now looking at a block with interference, and we know that either - // RegIn or RegOut is set. - assert(Intf.hasInterference() && (RegIn || RegOut) && "Bad invariant"); - - // If the live range is not live through the block, it is possible that the - // interference doesn't even overlap. Deal with those cases first. Since - // no copy instructions are required, we can tolerate interference starting - // or ending at the same instruction that kills or defines our live range. + // Block has interference. + DEBUG(dbgs() << ", interference to " << Intf.last()); - // Live-in, killed before interference. - // - // ~~~ Interference after kill. - // |---o---x | Killed in block. - // ========= Use MainIntv everywhere. - // - if (RegIn && !BI.LiveOut && BI.LastUse <= Intf.first()) { - DEBUG(dbgs() << ", live-in, killed before interference.\n"); - SE->selectIntv(MainIntv); - SlotIndex To = SE->leaveIntvAfter(BI.LastUse); - SE->useIntv(Start, To); + if (!BI.LiveThrough && Intf.last() <= BI.FirstUse) { + // The interference doesn't reach the outgoing segment. + DEBUG(dbgs() << " doesn't affect def from " << BI.FirstUse << '\n'); + SE->useIntv(BI.FirstUse, Stop); continue; } - // Live-out, defined after interference. - // - // ~~~ Interference before def. - // | o---o---| Defined in block. - // ========= Use MainIntv everywhere. - // - if (RegOut && !BI.LiveIn && BI.FirstUse >= Intf.last()) { - DEBUG(dbgs() << ", live-out, defined after interference.\n"); - SE->selectIntv(MainIntv); - SlotIndex From = SE->enterIntvBefore(BI.FirstUse); - SE->useIntv(From, Stop); - continue; + SlotIndex LastSplitPoint = SA->getLastSplitPoint(BI.MBB->getNumber()); + if (Intf.last().getBoundaryIndex() < BI.LastUse) { + // There are interference-free uses at the end of the block. + // Find the first use that can get the live-out register. + SmallVectorImpl::const_iterator UI = + std::lower_bound(SA->UseSlots.begin(), SA->UseSlots.end(), + Intf.last().getBoundaryIndex()); + assert(UI != SA->UseSlots.end() && "Couldn't find last use"); + SlotIndex Use = *UI; + assert(Use <= BI.LastUse && "Couldn't find last use"); + // Only attempt a split befroe the last split point. + if (Use.getBaseIndex() <= LastSplitPoint) { + DEBUG(dbgs() << ", free use at " << Use << ".\n"); + SlotIndex SegStart = SE->enterIntvBefore(Use); + assert(SegStart >= Intf.last() && "Couldn't avoid interference"); + assert(SegStart < LastSplitPoint && "Impossible split point"); + SE->useIntv(SegStart, Stop); + continue; + } } - // The interference is now known to overlap the live range, but it may - // still be easy to avoid if all the interference is on one side of the - // uses, and we enter or leave on the stack. + // Interference is after the last use. + DEBUG(dbgs() << " after last use.\n"); + SlotIndex SegStart = SE->enterIntvAtEnd(*BI.MBB); + assert(SegStart >= Intf.last() && "Couldn't avoid interference"); + } - // Live-out on stack, interference after last use. - // - // ~~~ Interference after last use. - // |---o---o---| Live-out on stack. - // =========____ Leave MainIntv after last use. - // - // ~ Interference after last use. - // |---o---o--o| Live-out on stack, late last use. - // =========____ Copy to stack after LSP, overlap MainIntv. - // - if (!RegOut && Intf.first() > BI.LastUse.getBoundaryIndex()) { - assert(RegIn && "Stack-in, stack-out should already be handled"); - if (BI.LastUse < LastSplitPoint) { - DEBUG(dbgs() << ", live-in, stack-out, interference after last use.\n"); - SE->selectIntv(MainIntv); - SlotIndex To = SE->leaveIntvAfter(BI.LastUse); - assert(To <= Intf.first() && "Expected to avoid interference"); - SE->useIntv(Start, To); - } else { - DEBUG(dbgs() << ", live-in, stack-out, avoid last split point\n"); - SE->selectIntv(MainIntv); - SlotIndex To = SE->leaveIntvBefore(LastSplitPoint); - assert(To <= Intf.first() && "Expected to avoid interference"); - SE->overlapIntv(To, BI.LastUse); - SE->useIntv(Start, To); + // Now all defs leading to live bundles are handled, do everything else. + for (unsigned i = 0; i != UseBlocks.size(); ++i) { + const SplitAnalysis::BlockInfo &BI = UseBlocks[i]; + bool RegIn = LiveBundles[Bundles->getBundle(BI.MBB->getNumber(), 0)]; + bool RegOut = LiveBundles[Bundles->getBundle(BI.MBB->getNumber(), 1)]; + + // Is the register live-in? + if (!BI.LiveIn || !RegIn) + continue; + + // We have an incoming register. Check for interference. + SlotIndex Start, Stop; + tie(Start, Stop) = Indexes->getMBBRange(BI.MBB); + Intf.moveToBlock(BI.MBB->getNumber()); + DEBUG(dbgs() << "EB#" << Bundles->getBundle(BI.MBB->getNumber(), 0) + << " -> BB#" << BI.MBB->getNumber() << " [" << Start << ';' + << SA->getLastSplitPoint(BI.MBB->getNumber()) << '-' << Stop + << ')'); + + // Check interference entering the block. + if (!Intf.hasInterference()) { + // Block is interference-free. + DEBUG(dbgs() << ", no interference"); + if (!BI.LiveThrough) { + DEBUG(dbgs() << ", killed in block.\n"); + SE->useIntv(Start, SE->leaveIntvAfter(BI.LastUse)); + continue; } + if (!RegOut) { + SlotIndex LastSplitPoint = SA->getLastSplitPoint(BI.MBB->getNumber()); + // Block is live-through, but exit bundle is on the stack. + // Spill immediately after the last use. + if (BI.LastUse < LastSplitPoint) { + DEBUG(dbgs() << ", uses, stack-out.\n"); + SE->useIntv(Start, SE->leaveIntvAfter(BI.LastUse)); + continue; + } + // The last use is after the last split point, it is probably an + // indirect jump. + DEBUG(dbgs() << ", uses at " << BI.LastUse << " after split point " + << LastSplitPoint << ", stack-out.\n"); + SlotIndex SegEnd = SE->leaveIntvBefore(LastSplitPoint); + SE->useIntv(Start, SegEnd); + // Run a double interval from the split to the last use. + // This makes it possible to spill the complement without affecting the + // indirect branch. + SE->overlapIntv(SegEnd, BI.LastUse); + continue; + } + // Register is live-through. + DEBUG(dbgs() << ", uses, live-through.\n"); + SE->useIntv(Start, Stop); continue; } - // Live-in on stack, interference before first use. - // - // ~~~ Interference before first use. - // |---o---o---| Live-in on stack. - // ____========= Enter MainIntv before first use. - // - if (!RegIn && Intf.last() < BI.FirstUse.getBaseIndex()) { - assert(RegOut && "Stack-in, stack-out should already be handled"); - DEBUG(dbgs() << ", stack-in, interference before first use.\n"); - SE->selectIntv(MainIntv); - SlotIndex From = SE->enterIntvBefore(BI.FirstUse); - assert(From >= Intf.last() && "Expected to avoid interference"); - SE->useIntv(From, Stop); + // Block has interference. + DEBUG(dbgs() << ", interference from " << Intf.first()); + + if (!BI.LiveThrough && Intf.first() >= BI.LastUse) { + // The interference doesn't reach the outgoing segment. + DEBUG(dbgs() << " doesn't affect kill at " << BI.LastUse << '\n'); + SE->useIntv(Start, BI.LastUse); continue; } - // The interference is overlapping somewhere we wanted to use MainIntv. That - // means we need to create a local interval that can be allocated a - // different register. - DEBUG(dbgs() << ", creating local interval.\n"); - unsigned LocalIntv = SE->openIntv(); - - // We may be creating copies directly between MainIntv and LocalIntv, - // bypassing the stack interval. When we do that, we should never use the - // leaveIntv* methods as they define values in the stack interval. By - // starting from the end of the block and working our way backwards, we can - // get by with only enterIntv* methods. - // - // When selecting split points, we generally try to maximize the stack - // interval as long at it contains no uses, maximize the main interval as - // long as it doesn't overlap interference, and minimize the local interval - // that we don't know how to allocate yet. - - // Handle the block exit, set Pos to the first handled slot. - SlotIndex Pos = BI.LastUse; - if (RegOut) { - assert(Intf.last() < LastSplitPoint && "Cannot be live-out in register"); - // Create a snippet of MainIntv that is live-out. - // - // ~~~ Interference overlapping uses. - // --o---| Live-out in MainIntv. - // ----=== Switch from LocalIntv to MainIntv after interference. - // - SE->selectIntv(MainIntv); - Pos = SE->enterIntvAfter(Intf.last()); - assert(Pos >= Intf.last() && "Expected to avoid interference"); - SE->useIntv(Pos, Stop); - SE->selectIntv(LocalIntv); - } else if (BI.LiveOut) { - if (BI.LastUse < LastSplitPoint) { - // Live-out on the stack. - // - // ~~~ Interference overlapping uses. - // --o---| Live-out on stack. - // ---____ Switch from LocalIntv to stack after last use. - // - Pos = SE->leaveIntvAfter(BI.LastUse); - } else { - // Live-out on the stack, last use after last split point. - // - // ~~~ Interference overlapping uses. - // --o--o| Live-out on stack, late use. - // ------ Copy to stack before LSP, overlap LocalIntv. - // \__ - // - Pos = SE->leaveIntvBefore(LastSplitPoint); - // We need to overlap LocalIntv so it can reach LastUse. - SE->overlapIntv(Pos, BI.LastUse); - } + if (Intf.first().getBaseIndex() > BI.FirstUse) { + // There are interference-free uses at the beginning of the block. + // Find the last use that can get the register. + SmallVectorImpl::const_iterator UI = + std::lower_bound(SA->UseSlots.begin(), SA->UseSlots.end(), + Intf.first().getBaseIndex()); + assert(UI != SA->UseSlots.begin() && "Couldn't find first use"); + SlotIndex Use = (--UI)->getBoundaryIndex(); + DEBUG(dbgs() << ", free use at " << *UI << ".\n"); + SlotIndex SegEnd = SE->leaveIntvAfter(Use); + assert(SegEnd <= Intf.first() && "Couldn't avoid interference"); + SE->useIntv(Start, SegEnd); + continue; } - // When not live-out, leave Pos at LastUse. We have handled everything from - // Pos to Stop. Find the starting point for LocalIntv. - assert(SE->currentIntv() == LocalIntv && "Expecting local interval"); - - if (RegIn) { - assert(Start < Intf.first() && "Cannot be live-in with interference"); - // Live-in in MainIntv, only use LocalIntv for interference. - // - // ~~~ Interference overlapping uses. - // |---o-- Live-in in MainIntv. - // ====--- Switch to LocalIntv before interference. - // - SlotIndex Switch = SE->enterIntvBefore(Intf.first()); - assert(Switch <= Intf.first() && "Expected to avoid interference"); - SE->useIntv(Switch, Pos); - SE->selectIntv(MainIntv); - SE->useIntv(Start, Switch); - } else { - // Live-in on stack, enter LocalIntv before first use. - // - // ~~~ Interference overlapping uses. - // |---o-- Live-in in MainIntv. - // ____--- Reload to LocalIntv before interference. - // - // Defined in block. - // - // ~~~ Interference overlapping uses. - // | o-- Defined in block. - // --- Begin LocalIntv at first use. - // - SlotIndex Switch = SE->enterIntvBefore(BI.FirstUse); - SE->useIntv(Switch, Pos); - } + // Interference is before the first use. + DEBUG(dbgs() << " before first use.\n"); + SlotIndex SegEnd = SE->leaveIntvAtTop(*BI.MBB); + assert(SegEnd <= Intf.first() && "Couldn't avoid interference"); } // Handle live-through blocks. - SE->selectIntv(MainIntv); for (unsigned i = 0, e = Cand.ActiveBlocks.size(); i != e; ++i) { unsigned Number = Cand.ActiveBlocks[i]; bool RegIn = LiveBundles[Bundles->getBundle(Number, 0)]; diff --git a/lib/CodeGen/SplitKit.cpp b/lib/CodeGen/SplitKit.cpp index a0952a0..55b1114 100644 --- a/lib/CodeGen/SplitKit.cpp +++ b/lib/CodeGen/SplitKit.cpp @@ -636,7 +636,6 @@ unsigned SplitEditor::openIntv() { void SplitEditor::selectIntv(unsigned Idx) { assert(Idx != 0 && "Cannot select the complement interval"); assert(Idx < Edit->size() && "Can only select previously opened interval"); - DEBUG(dbgs() << " selectIntv " << OpenIdx << " -> " << Idx << '\n'); OpenIdx = Idx; } @@ -657,24 +656,6 @@ SlotIndex SplitEditor::enterIntvBefore(SlotIndex Idx) { return VNI->def; } -SlotIndex SplitEditor::enterIntvAfter(SlotIndex Idx) { - assert(OpenIdx && "openIntv not called before enterIntvAfter"); - DEBUG(dbgs() << " enterIntvAfter " << Idx); - Idx = Idx.getBoundaryIndex(); - VNInfo *ParentVNI = Edit->getParent().getVNInfoAt(Idx); - if (!ParentVNI) { - DEBUG(dbgs() << ": not live\n"); - return Idx; - } - DEBUG(dbgs() << ": valno " << ParentVNI->id << '\n'); - MachineInstr *MI = LIS.getInstructionFromIndex(Idx); - assert(MI && "enterIntvAfter called with invalid index"); - - VNInfo *VNI = defFromParent(OpenIdx, ParentVNI, Idx, *MI->getParent(), - llvm::next(MachineBasicBlock::iterator(MI))); - return VNI->def; -} - SlotIndex SplitEditor::enterIntvAtEnd(MachineBasicBlock &MBB) { assert(OpenIdx && "openIntv not called before enterIntvAtEnd"); SlotIndex End = LIS.getMBBEndIdx(&MBB); @@ -1026,6 +1007,12 @@ void SplitEditor::finish(SmallVectorImpl *LRMap) { markComplexMapped(i, ParentVNI); } +#ifndef NDEBUG + // Every new interval must have a def by now, otherwise the split is bogus. + for (LiveRangeEdit::iterator I = Edit->begin(), E = Edit->end(); I != E; ++I) + assert((*I)->hasAtLeastOneValue() && "Split interval has no value"); +#endif + // Transfer the simply mapped values, check if any are skipped. bool Skipped = transferValues(); if (Skipped) diff --git a/lib/CodeGen/SplitKit.h b/lib/CodeGen/SplitKit.h index a9ccf40b..7174c0b 100644 --- a/lib/CodeGen/SplitKit.h +++ b/lib/CodeGen/SplitKit.h @@ -81,12 +81,6 @@ public: bool LiveThrough; ///< Live in whole block (Templ 5. above). bool LiveIn; ///< Current reg is live in. bool LiveOut; ///< Current reg is live out. - - /// isOneInstr - Returns true when this BlockInfo describes a single - /// instruction. - bool isOneInstr() const { - return SlotIndex::isSameInstr(FirstUse, LastUse); - } }; private: @@ -366,10 +360,6 @@ public: /// Return the beginning of the new live range. SlotIndex enterIntvBefore(SlotIndex Idx); - /// enterIntvAfter - Enter the open interval after the instruction at Idx. - /// Return the beginning of the new live range. - SlotIndex enterIntvAfter(SlotIndex Idx); - /// enterIntvAtEnd - Enter the open interval at the end of MBB. /// Use the open interval from he inserted copy to the MBB end. /// Return the beginning of the new live range. -- cgit v1.1 From 11745d4c0276ccb5c64f83d6954b54c8ff2aec98 Mon Sep 17 00:00:00 2001 From: Andrew Trick Date: Wed, 29 Jun 2011 03:13:40 +0000 Subject: indvars -disable-iv-rewrite: just because SCEV ignores casts doesn't mean they can be removed. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134054 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Scalar/IndVarSimplify.cpp | 1 + test/Transforms/IndVarSimplify/no-iv-rewrite.ll | 37 +++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/lib/Transforms/Scalar/IndVarSimplify.cpp b/lib/Transforms/Scalar/IndVarSimplify.cpp index 8986dbb..919da35 100644 --- a/lib/Transforms/Scalar/IndVarSimplify.cpp +++ b/lib/Transforms/Scalar/IndVarSimplify.cpp @@ -1007,6 +1007,7 @@ bool IndVarSimplify::EliminateIVUser(Instruction *UseInst, // Eliminate any operation that SCEV can prove is an identity function. if (!SE->isSCEVable(UseInst->getType()) || + (UseInst->getType() != IVOperand->getType()) || (SE->getSCEV(UseInst) != SE->getSCEV(IVOperand))) return false; diff --git a/test/Transforms/IndVarSimplify/no-iv-rewrite.ll b/test/Transforms/IndVarSimplify/no-iv-rewrite.ll index c35feef..462ff58 100644 --- a/test/Transforms/IndVarSimplify/no-iv-rewrite.ll +++ b/test/Transforms/IndVarSimplify/no-iv-rewrite.ll @@ -23,6 +23,7 @@ ph: ; sext should be eliminated while preserving gep inboundsness. ; CHECK-NOT: sext ; CHECK: getelementptr inbounds +; CHECK: exit loop: %i.02 = phi i32 [ 0, %ph ], [ %iinc, %loop ] %s.01 = phi i32 [ 0, %ph ], [ %sinc, %loop ] @@ -63,6 +64,7 @@ ph: ; CHECK: getelementptr inbounds ; %vall sext should obviously not be eliminated ; CHECK: sext +; CHECK: exit loop: %i.02 = phi i32 [ 0, %ph ], [ %iinc, %loop ] %s.01 = phi i64 [ 0, %ph ], [ %sinc, %loop ] @@ -106,6 +108,7 @@ ph: ; Preserve gep inboundsness, and don't factor it. ; CHECK: getelementptr inbounds i32* %ptriv, i32 1 ; CHECK-NOT: add +; CHECK: exit loop: %ptriv = phi i32* [ %first, %ph ], [ %ptrpost, %loop ] %ofs = sext i32 %idx to i64 @@ -121,3 +124,37 @@ exit: return: ret void } + +%struct = type { i32 } + +define void @bitcastiv(i32 %start, i32 %limit, i32 %step, %struct* %base) +nounwind +{ +entry: + br label %loop + +; CHECK: loop: +; +; Preserve casts +; CHECK: phi i32 +; CHECK: bitcast +; CHECK: getelementptr +; CHECK: exit +loop: + %iv = phi i32 [%start, %entry], [%next, %loop] + %p = phi %struct* [%base, %entry], [%pinc, %loop] + %adr = getelementptr %struct* %p, i32 0, i32 0 + store i32 3, i32* %adr + %pp = bitcast %struct* %p to i32* + store i32 4, i32* %pp + %pinc = getelementptr %struct* %p, i32 1 + %next = add i32 %iv, 1 + %cond = icmp ne i32 %next, %limit + br i1 %cond, label %loop, label %exit + +exit: + br label %return + +return: + ret void +} \ No newline at end of file -- cgit v1.1 From c4a84304a0a07b198e7dc3390b7afccf04e88b5c Mon Sep 17 00:00:00 2001 From: NAKAMURA Takumi Date: Wed, 29 Jun 2011 03:26:17 +0000 Subject: Fix CMake build. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134055 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/MC/CMakeLists.txt | 1 + lib/Target/CMakeLists.txt | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/MC/CMakeLists.txt b/lib/MC/CMakeLists.txt index a77ecd3..00e534f 100644 --- a/lib/MC/CMakeLists.txt +++ b/lib/MC/CMakeLists.txt @@ -34,6 +34,7 @@ add_llvm_library(LLVMMC MachObjectWriter.cpp WinCOFFStreamer.cpp WinCOFFObjectWriter.cpp + SubtargetFeature.cpp TargetAsmBackend.cpp ) diff --git a/lib/Target/CMakeLists.txt b/lib/Target/CMakeLists.txt index 09b48ce..7e2edd9 100644 --- a/lib/Target/CMakeLists.txt +++ b/lib/Target/CMakeLists.txt @@ -1,6 +1,5 @@ add_llvm_library(LLVMTarget Mangler.cpp - SubtargetFeature.cpp Target.cpp TargetAsmInfo.cpp TargetAsmLexer.cpp -- cgit v1.1 From 0fb7dcd48fd6580e3ebf35eafa952a9fe1cac8b2 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Wed, 29 Jun 2011 05:25:47 +0000 Subject: Let simplify cfg simplify bb with only debug and lifetime intrinsics. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134057 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/BasicBlock.h | 6 ++++++ lib/Transforms/Utils/Local.cpp | 22 ++++++++++++---------- lib/Transforms/Utils/SimplifyCFG.cpp | 2 +- lib/VMCore/BasicBlock.cpp | 20 ++++++++++++++++++++ test/Transforms/SimplifyCFG/lifetime.ll | 29 +++++++++++++++++++++++++++++ 5 files changed, 68 insertions(+), 11 deletions(-) create mode 100644 test/Transforms/SimplifyCFG/lifetime.ll diff --git a/include/llvm/BasicBlock.h b/include/llvm/BasicBlock.h index b02c249..3b953c0 100644 --- a/include/llvm/BasicBlock.h +++ b/include/llvm/BasicBlock.h @@ -138,6 +138,12 @@ public: return const_cast(this)->getFirstNonPHIOrDbg(); } + // Same as above, but also skip lifetime intrinsics. + Instruction* getFirstNonPHIOrDbgOrLifetime(); + const Instruction* getFirstNonPHIOrDbgOrLifetime() const { + return const_cast(this)->getFirstNonPHIOrDbgOrLifetime(); + } + /// removeFromParent - This method unlinks 'this' from the containing /// function, but does not delete it. /// diff --git a/lib/Transforms/Utils/Local.cpp b/lib/Transforms/Utils/Local.cpp index b1dd733..0046945 100644 --- a/lib/Transforms/Utils/Local.cpp +++ b/lib/Transforms/Utils/Local.cpp @@ -536,9 +536,9 @@ static bool CanPropagatePredecessorsForPHIs(BasicBlock *BB, BasicBlock *Succ) { /// TryToSimplifyUncondBranchFromEmptyBlock - BB is known to contain an /// unconditional branch, and contains no instructions other than PHI nodes, -/// potential debug intrinsics and the branch. If possible, eliminate BB by -/// rewriting all the predecessors to branch to the successor block and return -/// true. If we can't transform, return false. +/// potential side-effect free intrinsics and the branch. If possible, +/// eliminate BB by rewriting all the predecessors to branch to the successor +/// block and return true. If we can't transform, return false. bool llvm::TryToSimplifyUncondBranchFromEmptyBlock(BasicBlock *BB) { assert(BB != &BB->getParent()->getEntryBlock() && "TryToSimplifyUncondBranchFromEmptyBlock called on entry block!"); @@ -613,13 +613,15 @@ bool llvm::TryToSimplifyUncondBranchFromEmptyBlock(BasicBlock *BB) { } } - while (PHINode *PN = dyn_cast(&BB->front())) { - if (Succ->getSinglePredecessor()) { - // BB is the only predecessor of Succ, so Succ will end up with exactly - // the same predecessors BB had. - Succ->getInstList().splice(Succ->begin(), - BB->getInstList(), BB->begin()); - } else { + if (Succ->getSinglePredecessor()) { + // BB is the only predecessor of Succ, so Succ will end up with exactly + // the same predecessors BB had. + + // Copy over any phi, debug or lifetime instruction. + BB->getTerminator()->eraseFromParent(); + Succ->getInstList().splice(Succ->begin(), BB->getInstList()); + } else { + while (PHINode *PN = dyn_cast(&BB->front())) { // We explicitly check for such uses in CanPropagatePredecessorsForPHIs. assert(PN->use_empty() && "There shouldn't be any uses here!"); PN->eraseFromParent(); diff --git a/lib/Transforms/Utils/SimplifyCFG.cpp b/lib/Transforms/Utils/SimplifyCFG.cpp index 7b93b4a..49726d5 100644 --- a/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/lib/Transforms/Utils/SimplifyCFG.cpp @@ -2604,7 +2604,7 @@ bool SimplifyCFGOpt::SimplifyUncondBranch(BranchInst *BI, IRBuilder<> &Builder){ BasicBlock *BB = BI->getParent(); // If the Terminator is the only non-phi instruction, simplify the block. - BasicBlock::iterator I = BB->getFirstNonPHIOrDbg(); + BasicBlock::iterator I = BB->getFirstNonPHIOrDbgOrLifetime(); if (I->isTerminator() && BB != &BB->getParent()->getEntryBlock() && TryToSimplifyUncondBranchFromEmptyBlock(BB)) return true; diff --git a/lib/VMCore/BasicBlock.cpp b/lib/VMCore/BasicBlock.cpp index 7d47044..70265c8 100644 --- a/lib/VMCore/BasicBlock.cpp +++ b/lib/VMCore/BasicBlock.cpp @@ -147,6 +147,26 @@ Instruction* BasicBlock::getFirstNonPHIOrDbg() { return &*i; } +Instruction* BasicBlock::getFirstNonPHIOrDbgOrLifetime() { + // All valid basic blocks should have a terminator, + // which is not a PHINode. If we have an invalid basic + // block we'll get an assertion failure when dereferencing + // a past-the-end iterator. + BasicBlock::iterator i = begin(); + for (;; ++i) { + if (isa(i) || isa(i)) + continue; + + const IntrinsicInst *II = dyn_cast(i); + if (!II) + break; + if (II->getIntrinsicID() != Intrinsic::lifetime_start && + II->getIntrinsicID() != Intrinsic::lifetime_end) + break; + } + return &*i; +} + void BasicBlock::dropAllReferences() { for(iterator I = begin(), E = end(); I != E; ++I) I->dropAllReferences(); diff --git a/test/Transforms/SimplifyCFG/lifetime.ll b/test/Transforms/SimplifyCFG/lifetime.ll new file mode 100644 index 0000000..b794221 --- /dev/null +++ b/test/Transforms/SimplifyCFG/lifetime.ll @@ -0,0 +1,29 @@ +; RUN: opt < %s -simplifycfg -S | FileCheck %s + +; Test that a lifetime intrinsic doesn't prevent us from simplifying this. + +; CHECK: foo +; CHECK: entry: +; CHECK-NOT: bb0: +; CHECK-NOT: bb1: +; CHECK: ret +define void @foo(i1 %x) { +entry: + %a = alloca i8 + call void @llvm.lifetime.start(i64 -1, i8* %a) nounwind + br i1 %x, label %bb0, label %bb1 + +bb0: + call void @llvm.lifetime.end(i64 -1, i8* %a) nounwind + br label %bb1 + +bb1: + call void @f() + ret void +} + +declare void @f() + +declare void @llvm.lifetime.start(i64, i8* nocapture) nounwind + +declare void @llvm.lifetime.end(i64, i8* nocapture) nounwind -- cgit v1.1 From 2e10b0874447c8627a86d551f28f88620e0958c7 Mon Sep 17 00:00:00 2001 From: Francois Pichet Date: Wed, 29 Jun 2011 11:25:34 +0000 Subject: Change AsmName's type from StringRef to std::string. AsmName was pointing to a temporary string object that was destroyed. This is undefined behavior and MSVC didn't like it. This fixes over 300+ failing tests on MSVC. Credit for this fix goes to chapuni. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134064 91177308-0d34-0410-b5e6-96231b3b80d8 --- utils/TableGen/AsmWriterEmitter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/TableGen/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp index 53df7dd..b77d2e4 100644 --- a/utils/TableGen/AsmWriterEmitter.cpp +++ b/utils/TableGen/AsmWriterEmitter.cpp @@ -467,7 +467,7 @@ emitRegisterNameString(raw_ostream &O, StringRef AltName, for (unsigned i = 0, e = Registers.size(); i != e; ++i) { const CodeGenRegister &Reg = *Registers[i]; - StringRef AsmName; + std::string AsmName; // "NoRegAltName" is special. We don't need to do a lookup for that, // as it's just a reference to the default register name. if (AltName == "" || AltName == "NoRegAltName") { -- cgit v1.1 From bdd1ef2dbec63d4e428f4ff19d54821dc08fa168 Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Wed, 29 Jun 2011 13:47:25 +0000 Subject: Revert a part of r126557 which could create unschedulable DAGs. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134067 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 32 -------------------------------- test/CodeGen/X86/adde-carry.ll | 6 ------ 2 files changed, 38 deletions(-) diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index e3d3906..90e0cc7 100644 --- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -1310,16 +1310,6 @@ SDValue combineShlAddConstant(DebugLoc DL, SDValue N0, SDValue N1, return SDValue(); } -/// isCarryMaterialization - Returns true if V is an ADDE node that is known to -/// return 0 or 1 depending on the carry flag. -static bool isCarryMaterialization(SDValue V) { - if (V.getOpcode() != ISD::ADDE) - return false; - - ConstantSDNode *C = dyn_cast(V.getOperand(0)); - return C && C->isNullValue() && V.getOperand(0) == V.getOperand(1); -} - SDValue DAGCombiner::visitADD(SDNode *N) { SDValue N0 = N->getOperand(0); SDValue N1 = N->getOperand(1); @@ -1483,18 +1473,6 @@ SDValue DAGCombiner::visitADD(SDNode *N) { return DAG.getNode(ISD::SUB, DL, VT, N1, ZExt); } - // add (adde 0, 0, glue), X -> adde X, 0, glue - if (N0->hasOneUse() && isCarryMaterialization(N0)) - return DAG.getNode(ISD::ADDE, N->getDebugLoc(), - DAG.getVTList(VT, MVT::Glue), N1, N0.getOperand(0), - N0.getOperand(2)); - - // add X, (adde 0, 0, glue) -> adde X, 0, glue - if (N1->hasOneUse() && isCarryMaterialization(N1)) - return DAG.getNode(ISD::ADDE, N->getDebugLoc(), - DAG.getVTList(VT, MVT::Glue), N0, N1.getOperand(0), - N1.getOperand(2)); - return SDValue(); } @@ -1538,16 +1516,6 @@ SDValue DAGCombiner::visitADDC(SDNode *N) { N->getDebugLoc(), MVT::Glue)); } - // addc (adde 0, 0, glue), X -> adde X, 0, glue - if (N0->hasOneUse() && isCarryMaterialization(N0)) - return DAG.getNode(ISD::ADDE, N->getDebugLoc(), N->getVTList(), N1, - DAG.getConstant(0, VT), N0.getOperand(2)); - - // addc X, (adde 0, 0, glue) -> adde X, 0, glue - if (N1->hasOneUse() && isCarryMaterialization(N1)) - return DAG.getNode(ISD::ADDE, N->getDebugLoc(), N->getVTList(), N0, - DAG.getConstant(0, VT), N1.getOperand(2)); - return SDValue(); } diff --git a/test/CodeGen/X86/adde-carry.ll b/test/CodeGen/X86/adde-carry.ll index 98c4f99..e86adf4 100644 --- a/test/CodeGen/X86/adde-carry.ll +++ b/test/CodeGen/X86/adde-carry.ll @@ -1,5 +1,4 @@ ; RUN: llc -march=x86-64 < %s | FileCheck %s -check-prefix=CHECK-64 -; RUN: llc -march=x86 < %s | FileCheck %s -check-prefix=CHECK-32 define void @a(i64* nocapture %s, i64* nocapture %t, i64 %a, i64 %b, i64 %c) nounwind { entry: @@ -16,11 +15,6 @@ entry: store i64 %8, i64* %t, align 8 ret void -; CHECK-32: addl -; CHECK-32: adcl -; CHECK-32: adcl $0 -; CHECK-32: adcl $0 - ; CHECK-64: addq ; CHECK-64: adcq $0 } -- cgit v1.1 From 8981bce73f3a733aa29f6be32cf8703c6cc2d7c8 Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Wed, 29 Jun 2011 14:07:18 +0000 Subject: Don't depend on the optimization reverted in r134067. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134068 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/CodeGen/ARM/carry.ll | 1 - test/CodeGen/Thumb2/thumb2-sbc.ll | 1 - 2 files changed, 2 deletions(-) diff --git a/test/CodeGen/ARM/carry.ll b/test/CodeGen/ARM/carry.ll index 9b90408..06b459e 100644 --- a/test/CodeGen/ARM/carry.ll +++ b/test/CodeGen/ARM/carry.ll @@ -24,7 +24,6 @@ entry: define i64 @f3(i32 %al, i32 %bl) { ; CHECK: f3: ; CHECK: adds r -; CHECK: adcs r ; CHECK: adc r entry: ; unsigned wide add diff --git a/test/CodeGen/Thumb2/thumb2-sbc.ll b/test/CodeGen/Thumb2/thumb2-sbc.ll index 53f45ea..492e5f0 100644 --- a/test/CodeGen/Thumb2/thumb2-sbc.ll +++ b/test/CodeGen/Thumb2/thumb2-sbc.ll @@ -56,7 +56,6 @@ define i64 @f6(i64 %a) { ; ; CHECK: livecarry: ; CHECK: adds -; CHECK: adcs ; CHECK: adc define i64 @livecarry(i64 %carry, i32 %digit) nounwind { %ch = lshr i64 %carry, 32 -- cgit v1.1 From 254cf03a45534ccfdcc7d223fbebc07d4a0562a7 Mon Sep 17 00:00:00 2001 From: Jim Grosbach Date: Wed, 29 Jun 2011 16:05:14 +0000 Subject: Asm parser range checking on . directives. For example, ".byte 256" would previously assert() when emitting an object file. Now it generates a diagnostic that the literal value is out of range. rdar://9686950 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134069 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/MC/MCParser/AsmParser.cpp | 12 +++++++++--- test/MC/AsmParser/exprs-invalid.s | 6 ++++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index 7b62db2..db188f7 100644 --- a/lib/MC/MCParser/AsmParser.cpp +++ b/lib/MC/MCParser/AsmParser.cpp @@ -28,6 +28,7 @@ #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCDwarf.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/MathExtras.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/raw_ostream.h" @@ -1612,13 +1613,18 @@ bool AsmParser::ParseDirectiveValue(unsigned Size) { for (;;) { const MCExpr *Value; + SMLoc ExprLoc = getLexer().getLoc(); if (ParseExpression(Value)) return true; // Special case constant expressions to match code generator. - if (const MCConstantExpr *MCE = dyn_cast(Value)) - getStreamer().EmitIntValue(MCE->getValue(), Size, DEFAULT_ADDRSPACE); - else + if (const MCConstantExpr *MCE = dyn_cast(Value)) { + assert(Size <= 8 && "Invalid size"); + uint64_t IntValue = MCE->getValue(); + if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue)) + return Error(ExprLoc, "literal value out of range for directive"); + getStreamer().EmitIntValue(IntValue, Size, DEFAULT_ADDRSPACE); + } else getStreamer().EmitValue(Value, Size, DEFAULT_ADDRSPACE); if (getLexer().is(AsmToken::EndOfStatement)) diff --git a/test/MC/AsmParser/exprs-invalid.s b/test/MC/AsmParser/exprs-invalid.s index dc27d80..88b2a0a 100644 --- a/test/MC/AsmParser/exprs-invalid.s +++ b/test/MC/AsmParser/exprs-invalid.s @@ -6,3 +6,9 @@ // CHECK-ERRORS: error: invalid hexadecimal number .long 80+0xzz + +// CHECK-ERRORS: error: literal value out of range for directive +.byte 256 + +// CHECK-ERRORS: error: literal value out of range for directive +.long 4e71cf69 // double floating point constant due to missing "0x" -- cgit v1.1 From ce77aa3edc0d07c8a2b9a613d9b57457dee43425 Mon Sep 17 00:00:00 2001 From: Chad Rosier Date: Wed, 29 Jun 2011 16:22:11 +0000 Subject: Temporarily revert r134057: "Let simplify cfg simplify bb with only debug and lifetime intrinsics" due to buildbot failures. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134071 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/BasicBlock.h | 6 ------ lib/Transforms/Utils/Local.cpp | 22 ++++++++++------------ lib/Transforms/Utils/SimplifyCFG.cpp | 2 +- lib/VMCore/BasicBlock.cpp | 20 -------------------- test/Transforms/SimplifyCFG/lifetime.ll | 29 ----------------------------- 5 files changed, 11 insertions(+), 68 deletions(-) delete mode 100644 test/Transforms/SimplifyCFG/lifetime.ll diff --git a/include/llvm/BasicBlock.h b/include/llvm/BasicBlock.h index 3b953c0..b02c249 100644 --- a/include/llvm/BasicBlock.h +++ b/include/llvm/BasicBlock.h @@ -138,12 +138,6 @@ public: return const_cast(this)->getFirstNonPHIOrDbg(); } - // Same as above, but also skip lifetime intrinsics. - Instruction* getFirstNonPHIOrDbgOrLifetime(); - const Instruction* getFirstNonPHIOrDbgOrLifetime() const { - return const_cast(this)->getFirstNonPHIOrDbgOrLifetime(); - } - /// removeFromParent - This method unlinks 'this' from the containing /// function, but does not delete it. /// diff --git a/lib/Transforms/Utils/Local.cpp b/lib/Transforms/Utils/Local.cpp index 0046945..b1dd733 100644 --- a/lib/Transforms/Utils/Local.cpp +++ b/lib/Transforms/Utils/Local.cpp @@ -536,9 +536,9 @@ static bool CanPropagatePredecessorsForPHIs(BasicBlock *BB, BasicBlock *Succ) { /// TryToSimplifyUncondBranchFromEmptyBlock - BB is known to contain an /// unconditional branch, and contains no instructions other than PHI nodes, -/// potential side-effect free intrinsics and the branch. If possible, -/// eliminate BB by rewriting all the predecessors to branch to the successor -/// block and return true. If we can't transform, return false. +/// potential debug intrinsics and the branch. If possible, eliminate BB by +/// rewriting all the predecessors to branch to the successor block and return +/// true. If we can't transform, return false. bool llvm::TryToSimplifyUncondBranchFromEmptyBlock(BasicBlock *BB) { assert(BB != &BB->getParent()->getEntryBlock() && "TryToSimplifyUncondBranchFromEmptyBlock called on entry block!"); @@ -613,15 +613,13 @@ bool llvm::TryToSimplifyUncondBranchFromEmptyBlock(BasicBlock *BB) { } } - if (Succ->getSinglePredecessor()) { - // BB is the only predecessor of Succ, so Succ will end up with exactly - // the same predecessors BB had. - - // Copy over any phi, debug or lifetime instruction. - BB->getTerminator()->eraseFromParent(); - Succ->getInstList().splice(Succ->begin(), BB->getInstList()); - } else { - while (PHINode *PN = dyn_cast(&BB->front())) { + while (PHINode *PN = dyn_cast(&BB->front())) { + if (Succ->getSinglePredecessor()) { + // BB is the only predecessor of Succ, so Succ will end up with exactly + // the same predecessors BB had. + Succ->getInstList().splice(Succ->begin(), + BB->getInstList(), BB->begin()); + } else { // We explicitly check for such uses in CanPropagatePredecessorsForPHIs. assert(PN->use_empty() && "There shouldn't be any uses here!"); PN->eraseFromParent(); diff --git a/lib/Transforms/Utils/SimplifyCFG.cpp b/lib/Transforms/Utils/SimplifyCFG.cpp index 49726d5..7b93b4a 100644 --- a/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/lib/Transforms/Utils/SimplifyCFG.cpp @@ -2604,7 +2604,7 @@ bool SimplifyCFGOpt::SimplifyUncondBranch(BranchInst *BI, IRBuilder<> &Builder){ BasicBlock *BB = BI->getParent(); // If the Terminator is the only non-phi instruction, simplify the block. - BasicBlock::iterator I = BB->getFirstNonPHIOrDbgOrLifetime(); + BasicBlock::iterator I = BB->getFirstNonPHIOrDbg(); if (I->isTerminator() && BB != &BB->getParent()->getEntryBlock() && TryToSimplifyUncondBranchFromEmptyBlock(BB)) return true; diff --git a/lib/VMCore/BasicBlock.cpp b/lib/VMCore/BasicBlock.cpp index 70265c8..7d47044 100644 --- a/lib/VMCore/BasicBlock.cpp +++ b/lib/VMCore/BasicBlock.cpp @@ -147,26 +147,6 @@ Instruction* BasicBlock::getFirstNonPHIOrDbg() { return &*i; } -Instruction* BasicBlock::getFirstNonPHIOrDbgOrLifetime() { - // All valid basic blocks should have a terminator, - // which is not a PHINode. If we have an invalid basic - // block we'll get an assertion failure when dereferencing - // a past-the-end iterator. - BasicBlock::iterator i = begin(); - for (;; ++i) { - if (isa(i) || isa(i)) - continue; - - const IntrinsicInst *II = dyn_cast(i); - if (!II) - break; - if (II->getIntrinsicID() != Intrinsic::lifetime_start && - II->getIntrinsicID() != Intrinsic::lifetime_end) - break; - } - return &*i; -} - void BasicBlock::dropAllReferences() { for(iterator I = begin(), E = end(); I != E; ++I) I->dropAllReferences(); diff --git a/test/Transforms/SimplifyCFG/lifetime.ll b/test/Transforms/SimplifyCFG/lifetime.ll deleted file mode 100644 index b794221..0000000 --- a/test/Transforms/SimplifyCFG/lifetime.ll +++ /dev/null @@ -1,29 +0,0 @@ -; RUN: opt < %s -simplifycfg -S | FileCheck %s - -; Test that a lifetime intrinsic doesn't prevent us from simplifying this. - -; CHECK: foo -; CHECK: entry: -; CHECK-NOT: bb0: -; CHECK-NOT: bb1: -; CHECK: ret -define void @foo(i1 %x) { -entry: - %a = alloca i8 - call void @llvm.lifetime.start(i64 -1, i8* %a) nounwind - br i1 %x, label %bb0, label %bb1 - -bb0: - call void @llvm.lifetime.end(i64 -1, i8* %a) nounwind - br label %bb1 - -bb1: - call void @f() - ret void -} - -declare void @f() - -declare void @llvm.lifetime.start(i64, i8* nocapture) nounwind - -declare void @llvm.lifetime.end(i64, i8* nocapture) nounwind -- cgit v1.1 From 0b0669a0568331122e545c93c6580786cf0cafdd Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Wed, 29 Jun 2011 17:14:00 +0000 Subject: Add missing operand. rdar://9694169 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134078 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/LangRef.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/LangRef.html b/docs/LangRef.html index 7823f12..74b2391 100644 --- a/docs/LangRef.html +++ b/docs/LangRef.html @@ -7309,7 +7309,7 @@ LLVM.

store i32 4, %ptr %result1 = load i32* %ptr ; yields {i32}:result1 = 4 - call void @llvm.memory.barrier(i1 false, i1 true, i1 false, i1 false) + call void @llvm.memory.barrier(i1 false, i1 true, i1 false, i1 false, i1 true) ; guarantee the above finishes store i32 8, %ptr ; before this begins -- cgit v1.1 From d176af8cf3e3b3fb39385798e25e55449933648c Mon Sep 17 00:00:00 2001 From: Eric Christopher Date: Wed, 29 Jun 2011 17:23:50 +0000 Subject: Use getRegForInlineAsmConstraint instead of custom defining regclasses via vectors. Part of rdar://9643582 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134079 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86ISelLowering.cpp | 76 ++++++++++++-------------------------- lib/Target/X86/X86ISelLowering.h | 4 -- 2 files changed, 24 insertions(+), 56 deletions(-) diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index b327f1b..4f8b90f 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -12875,69 +12875,41 @@ void X86TargetLowering::LowerAsmOperandForConstraint(SDValue Op, return TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, Ops, DAG); } -std::vector X86TargetLowering:: -getRegClassForInlineAsmConstraint(const std::string &Constraint, - EVT VT) const { +std::pair +X86TargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint, + EVT VT) const { + // First, see if this is a constraint that directly corresponds to an LLVM + // register class. if (Constraint.size() == 1) { - // FIXME: not handling fp-stack yet! - switch (Constraint[0]) { // GCC X86 Constraint Letters - default: break; // Unknown constraint letter + // GCC Constraint Letters + switch (Constraint[0]) { + default: break; + // TODO: Slight differences here in allocation order and leaving + // RIP in the class. Do they matter any more here than they do + // in the normal allocation? case 'q': // GENERAL_REGS in 64-bit mode, Q_REGS in 32-bit mode. if (Subtarget->is64Bit()) { - if (VT == MVT::i32) - return make_vector(X86::EAX, X86::EDX, X86::ECX, X86::EBX, - X86::ESI, X86::EDI, X86::R8D, X86::R9D, - X86::R10D,X86::R11D,X86::R12D, - X86::R13D,X86::R14D,X86::R15D, - X86::EBP, X86::ESP, 0); - else if (VT == MVT::i16) - return make_vector(X86::AX, X86::DX, X86::CX, X86::BX, - X86::SI, X86::DI, X86::R8W,X86::R9W, - X86::R10W,X86::R11W,X86::R12W, - X86::R13W,X86::R14W,X86::R15W, - X86::BP, X86::SP, 0); - else if (VT == MVT::i8) - return make_vector(X86::AL, X86::DL, X86::CL, X86::BL, - X86::SIL, X86::DIL, X86::R8B,X86::R9B, - X86::R10B,X86::R11B,X86::R12B, - X86::R13B,X86::R14B,X86::R15B, - X86::BPL, X86::SPL, 0); - - else if (VT == MVT::i64) - return make_vector(X86::RAX, X86::RDX, X86::RCX, X86::RBX, - X86::RSI, X86::RDI, X86::R8, X86::R9, - X86::R10, X86::R11, X86::R12, - X86::R13, X86::R14, X86::R15, - X86::RBP, X86::RSP, 0); - - break; + if (VT == MVT::i32) + return std::make_pair(0U, X86::GR32RegisterClass); + else if (VT == MVT::i16) + return std::make_pair(0U, X86::GR16RegisterClass); + else if (VT == MVT::i8) + return std::make_pair(0U, X86::GR8RegisterClass); + else if (VT == MVT::i64) + return std::make_pair(0U, X86::GR64RegisterClass); + break; } // 32-bit fallthrough case 'Q': // Q_REGS if (VT == MVT::i32) - return make_vector(X86::EAX, X86::EDX, X86::ECX, X86::EBX, 0); + return std::make_pair(0U, X86::GR32_ABCDRegisterClass); else if (VT == MVT::i16) - return make_vector(X86::AX, X86::DX, X86::CX, X86::BX, 0); + return std::make_pair(0U, X86::GR16_ABCDRegisterClass); else if (VT == MVT::i8) - return make_vector(X86::AL, X86::DL, X86::CL, X86::BL, 0); + return std::make_pair(0U, X86::GR8_ABCD_LRegisterClass); else if (VT == MVT::i64) - return make_vector(X86::RAX, X86::RDX, X86::RCX, X86::RBX, 0); + return std::make_pair(0U, X86::GR64_ABCDRegisterClass); break; - } - } - - return std::vector(); -} - -std::pair -X86TargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint, - EVT VT) const { - // First, see if this is a constraint that directly corresponds to an LLVM - // register class. - if (Constraint.size() == 1) { - // GCC Constraint Letters - switch (Constraint[0]) { - default: break; case 'r': // GENERAL_REGS case 'l': // INDEX_REGS if (VT == MVT::i8) diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h index cbe2389..d9c883f 100644 --- a/lib/Target/X86/X86ISelLowering.h +++ b/lib/Target/X86/X86ISelLowering.h @@ -596,10 +596,6 @@ namespace llvm { virtual ConstraintWeight getSingleConstraintMatchWeight( AsmOperandInfo &info, const char *constraint) const; - std::vector - getRegClassForInlineAsmConstraint(const std::string &Constraint, - EVT VT) const; - virtual const char *LowerXConstraint(EVT ConstraintVT) const; /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops -- cgit v1.1 From ca42299619cf47371a42c2bda87d067e003657ea Mon Sep 17 00:00:00 2001 From: Eric Christopher Date: Wed, 29 Jun 2011 17:53:29 +0000 Subject: Move XCore from getRegClassForInlineAsmConstraint to getRegForInlineAsmConstraint. Part of rdar://9643582 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134080 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/XCore/XCoreISelLowering.cpp | 25 +++++++++++-------------- lib/Target/XCore/XCoreISelLowering.h | 6 +++--- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/lib/Target/XCore/XCoreISelLowering.cpp b/lib/Target/XCore/XCoreISelLowering.cpp index 8cabbbf..6d040e0 100644 --- a/lib/Target/XCore/XCoreISelLowering.cpp +++ b/lib/Target/XCore/XCoreISelLowering.cpp @@ -1591,21 +1591,18 @@ XCoreTargetLowering::isLegalAddressingMode(const AddrMode &AM, // XCore Inline Assembly Support //===----------------------------------------------------------------------===// -std::vector XCoreTargetLowering:: -getRegClassForInlineAsmConstraint(const std::string &Constraint, - EVT VT) const -{ - if (Constraint.size() != 1) - return std::vector(); - - switch (Constraint[0]) { +std::pair +XCoreTargetLowering:: +getRegForInlineAsmConstraint(const std::string &Constraint, + EVT VT) const { + if (Constraint.size() == 1) { + switch (Constraint[0]) { default : break; case 'r': - return make_vector(XCore::R0, XCore::R1, XCore::R2, - XCore::R3, XCore::R4, XCore::R5, - XCore::R6, XCore::R7, XCore::R8, - XCore::R9, XCore::R10, XCore::R11, 0); - break; + return std::make_pair(0U, XCore::GRRegsRegisterClass); + } } - return std::vector(); + // Use the default implementation in TargetLowering to convert the register + // constraint into a member of a register class. + return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT); } diff --git a/lib/Target/XCore/XCoreISelLowering.h b/lib/Target/XCore/XCoreISelLowering.h index a8d67d4..9c803be 100644 --- a/lib/Target/XCore/XCoreISelLowering.h +++ b/lib/Target/XCore/XCoreISelLowering.h @@ -148,9 +148,9 @@ namespace llvm { SDValue LowerTRAMPOLINE(SDValue Op, SelectionDAG &DAG) const; // Inline asm support - std::vector - getRegClassForInlineAsmConstraint(const std::string &Constraint, - EVT VT) const; + std::pair + getRegForInlineAsmConstraint(const std::string &Constraint, + EVT VT) const; // Expand specifics SDValue TryExpandADDWithMul(SDNode *Op, SelectionDAG &DAG) const; -- cgit v1.1 From 158bf50787f1881fbdb6f62761d15aae0d3862f6 Mon Sep 17 00:00:00 2001 From: Eric Christopher Date: Wed, 29 Jun 2011 18:53:10 +0000 Subject: Remove getRegClassForInlineAsmConstraint from sparc. Part of rdar://9643582 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134083 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Sparc/SparcISelLowering.cpp | 21 --------------------- lib/Target/Sparc/SparcISelLowering.h | 3 --- 2 files changed, 24 deletions(-) diff --git a/lib/Target/Sparc/SparcISelLowering.cpp b/lib/Target/Sparc/SparcISelLowering.cpp index 0b4612d..a2bda6c 100644 --- a/lib/Target/Sparc/SparcISelLowering.cpp +++ b/lib/Target/Sparc/SparcISelLowering.cpp @@ -1,4 +1,3 @@ - //===-- SparcISelLowering.cpp - Sparc DAG Lowering Implementation ---------===// // // The LLVM Compiler Infrastructure @@ -1265,26 +1264,6 @@ SparcTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint, return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT); } -std::vector SparcTargetLowering:: -getRegClassForInlineAsmConstraint(const std::string &Constraint, - EVT VT) const { - if (Constraint.size() != 1) - return std::vector(); - - switch (Constraint[0]) { - default: break; - case 'r': - return make_vector(SP::L0, SP::L1, SP::L2, SP::L3, - SP::L4, SP::L5, SP::L6, SP::L7, - SP::I0, SP::I1, SP::I2, SP::I3, - SP::I4, SP::I5, - SP::O0, SP::O1, SP::O2, SP::O3, - SP::O4, SP::O5, SP::O7, 0); - } - - return std::vector(); -} - bool SparcTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const { // The Sparc target isn't yet aware of offsets. diff --git a/lib/Target/Sparc/SparcISelLowering.h b/lib/Target/Sparc/SparcISelLowering.h index 9ea6e16..8a1886a 100644 --- a/lib/Target/Sparc/SparcISelLowering.h +++ b/lib/Target/Sparc/SparcISelLowering.h @@ -65,9 +65,6 @@ namespace llvm { ConstraintType getConstraintType(const std::string &Constraint) const; std::pair getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const; - std::vector - getRegClassForInlineAsmConstraint(const std::string &Constraint, - EVT VT) const; virtual bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const; -- cgit v1.1 From 314aff1474034140a4c5bf3a855963d5259bf90d Mon Sep 17 00:00:00 2001 From: Eric Christopher Date: Wed, 29 Jun 2011 19:04:31 +0000 Subject: Remove getRegClassForInlineAsmConstraint for Mips. Part of rdar://9643582 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134084 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Mips/MipsISelLowering.cpp | 47 +++--------------------------------- lib/Target/Mips/MipsISelLowering.h | 4 --- 2 files changed, 3 insertions(+), 48 deletions(-) diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index e29c8f6..8bd7e75 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -2337,6 +2337,8 @@ getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const { if (Constraint.size() == 1) { switch (Constraint[0]) { + case 'd': // Address register. Same as 'r' unless generating MIPS16 code. + case 'y': // Same as 'r'. Exists for compatibility. case 'r': return std::make_pair(0U, Mips::CPURegsRegisterClass); case 'f': @@ -2345,55 +2347,12 @@ getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const if (VT == MVT::f64) if ((!Subtarget->isSingleFloat()) && (!Subtarget->isFP64bit())) return std::make_pair(0U, Mips::AFGR64RegisterClass); + break; } } return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT); } -/// Given a register class constraint, like 'r', if this corresponds directly -/// to an LLVM register class, return a register of 0 and the register class -/// pointer. -std::vector MipsTargetLowering:: -getRegClassForInlineAsmConstraint(const std::string &Constraint, - EVT VT) const -{ - if (Constraint.size() != 1) - return std::vector(); - - switch (Constraint[0]) { - default : break; - case 'r': - // GCC Mips Constraint Letters - case 'd': - case 'y': - return make_vector(Mips::T0, Mips::T1, Mips::T2, Mips::T3, - Mips::T4, Mips::T5, Mips::T6, Mips::T7, Mips::S0, Mips::S1, - Mips::S2, Mips::S3, Mips::S4, Mips::S5, Mips::S6, Mips::S7, - Mips::T8, 0); - - case 'f': - if (VT == MVT::f32) { - if (Subtarget->isSingleFloat()) - return make_vector(Mips::F2, Mips::F3, Mips::F4, Mips::F5, - Mips::F6, Mips::F7, Mips::F8, Mips::F9, Mips::F10, Mips::F11, - Mips::F20, Mips::F21, Mips::F22, Mips::F23, Mips::F24, - Mips::F25, Mips::F26, Mips::F27, Mips::F28, Mips::F29, - Mips::F30, Mips::F31, 0); - else - return make_vector(Mips::F2, Mips::F4, Mips::F6, Mips::F8, - Mips::F10, Mips::F20, Mips::F22, Mips::F24, Mips::F26, - Mips::F28, Mips::F30, 0); - } - - if (VT == MVT::f64) - if ((!Subtarget->isSingleFloat()) && (!Subtarget->isFP64bit())) - return make_vector(Mips::D1, Mips::D2, Mips::D3, Mips::D4, - Mips::D5, Mips::D10, Mips::D11, Mips::D12, Mips::D13, - Mips::D14, Mips::D15, 0); - } - return std::vector(); -} - bool MipsTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const { // The Mips target isn't yet aware of offsets. diff --git a/lib/Target/Mips/MipsISelLowering.h b/lib/Target/Mips/MipsISelLowering.h index b7b85fd..bda26a2 100644 --- a/lib/Target/Mips/MipsISelLowering.h +++ b/lib/Target/Mips/MipsISelLowering.h @@ -169,10 +169,6 @@ namespace llvm { getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const; - std::vector - getRegClassForInlineAsmConstraint(const std::string &Constraint, - EVT VT) const; - virtual bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const; /// isFPImmLegal - Returns true if the target can instruction select the -- cgit v1.1 From 193f7e2eb01943900779e51513d6f5e709326dfa Mon Sep 17 00:00:00 2001 From: Eric Christopher Date: Wed, 29 Jun 2011 19:12:24 +0000 Subject: Remove getRegClassForInlineAsmConstraint from MBlaze. Add a TODO comment for the port. Part of rdar://9643582 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134085 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/MBlaze/MBlazeISelLowering.cpp | 36 +++++++------------------------- lib/Target/MBlaze/MBlazeISelLowering.h | 4 ---- 2 files changed, 7 insertions(+), 33 deletions(-) diff --git a/lib/Target/MBlaze/MBlazeISelLowering.cpp b/lib/Target/MBlaze/MBlazeISelLowering.cpp index c5e0a89..ba2de40 100644 --- a/lib/Target/MBlaze/MBlazeISelLowering.cpp +++ b/lib/Target/MBlaze/MBlazeISelLowering.cpp @@ -1114,15 +1114,19 @@ MBlazeTargetLowering::getSingleConstraintMatchWeight( return weight; } -/// getRegClassForInlineAsmConstraint - Given a constraint letter (e.g. "r"), -/// return a list of registers that can be used to satisfy the constraint. -/// This should only be used for C_RegisterClass constraints. +/// Given a register class constraint, like 'r', if this corresponds directly +/// to an LLVM register class, return a register of 0 and the register class +/// pointer. std::pair MBlazeTargetLowering:: getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const { if (Constraint.size() == 1) { switch (Constraint[0]) { case 'r': return std::make_pair(0U, MBlaze::GPRRegisterClass); + // TODO: These can't possibly be right, but match what was in + // getRegClassForInlineAsmConstraint. + case 'd': + case 'y': case 'f': if (VT == MVT::f32) return std::make_pair(0U, MBlaze::GPRRegisterClass); @@ -1131,32 +1135,6 @@ getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const { return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT); } -/// Given a register class constraint, like 'r', if this corresponds directly -/// to an LLVM register class, return a register of 0 and the register class -/// pointer. -std::vector MBlazeTargetLowering:: -getRegClassForInlineAsmConstraint(const std::string &Constraint, EVT VT) const { - if (Constraint.size() != 1) - return std::vector(); - - switch (Constraint[0]) { - default : break; - case 'r': - // GCC MBlaze Constraint Letters - case 'd': - case 'y': - case 'f': - return make_vector( - MBlaze::R3, MBlaze::R4, MBlaze::R5, MBlaze::R6, - MBlaze::R7, MBlaze::R9, MBlaze::R10, MBlaze::R11, - MBlaze::R12, MBlaze::R19, MBlaze::R20, MBlaze::R21, - MBlaze::R22, MBlaze::R23, MBlaze::R24, MBlaze::R25, - MBlaze::R26, MBlaze::R27, MBlaze::R28, MBlaze::R29, - MBlaze::R30, MBlaze::R31, 0); - } - return std::vector(); -} - bool MBlazeTargetLowering:: isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const { // The MBlaze target isn't yet aware of offsets. diff --git a/lib/Target/MBlaze/MBlazeISelLowering.h b/lib/Target/MBlaze/MBlazeISelLowering.h index 265c1a7..bb128da 100644 --- a/lib/Target/MBlaze/MBlazeISelLowering.h +++ b/lib/Target/MBlaze/MBlazeISelLowering.h @@ -173,10 +173,6 @@ namespace llvm { getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const; - std::vector - getRegClassForInlineAsmConstraint(const std::string &Constraint, - EVT VT) const; - virtual bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const; /// isFPImmLegal - Returns true if the target can instruction select the -- cgit v1.1 From 1c24ba9fad4e668ad854f1ff544e60c347c6d341 Mon Sep 17 00:00:00 2001 From: Eric Christopher Date: Wed, 29 Jun 2011 19:30:29 +0000 Subject: Move the Blackfin port away from getRegClassForInlineAsmConstraint by creating a few specific register classes. Part of rdar://9643582 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134086 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Blackfin/BlackfinISelLowering.cpp | 34 +++++++--------------------- lib/Target/Blackfin/BlackfinISelLowering.h | 3 --- lib/Target/Blackfin/BlackfinRegisterInfo.td | 14 ++++++++++++ 3 files changed, 22 insertions(+), 29 deletions(-) diff --git a/lib/Target/Blackfin/BlackfinISelLowering.cpp b/lib/Target/Blackfin/BlackfinISelLowering.cpp index 588d9bd..d572832 100644 --- a/lib/Target/Blackfin/BlackfinISelLowering.cpp +++ b/lib/Target/Blackfin/BlackfinISelLowering.cpp @@ -621,39 +621,21 @@ getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const { case 'w': return Pair(0U, ALLRegisterClass); case 'Z': return Pair(P3, PRegisterClass); case 'Y': return Pair(P1, PRegisterClass); + case 'z': return Pair(0U, zConsRegisterClass); + case 'D': return Pair(0U, DConsRegisterClass); + case 'W': return Pair(0U, WConsRegisterClass); + case 'c': return Pair(0U, cConsRegisterClass); + case 't': return Pair(0U, tConsRegisterClass); + case 'u': return Pair(0U, uConsRegisterClass); + case 'k': return Pair(0U, kConsRegisterClass); + case 'y': return Pair(0U, yConsRegisterClass); } // Not implemented: q0-q7, qA. Use {R2} etc instead. - // Constraints z, D, W, c, t, u, k, and y use non-existing classes, defer to - // getRegClassForInlineAsmConstraint() return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT); } -std::vector BlackfinTargetLowering:: -getRegClassForInlineAsmConstraint(const std::string &Constraint, EVT VT) const { - using namespace BF; - - if (Constraint.size() != 1) - return std::vector(); - - switch (Constraint[0]) { - case 'z': return make_vector(P0, P1, P2, 0); - case 'D': return make_vector(R0, R2, R4, R6, 0); - case 'W': return make_vector(R1, R3, R5, R7, 0); - case 'c': return make_vector(I0, I1, I2, I3, - B0, B1, B2, B3, - L0, L1, L2, L3, 0); - case 't': return make_vector(LT0, LT1, 0); - case 'u': return make_vector(LB0, LB1, 0); - case 'k': return make_vector(LC0, LC1, 0); - case 'y': return make_vector(RETS, RETN, RETI, RETX, RETE, - ASTAT, SEQSTAT, USP, 0); - } - - return std::vector(); -} - bool BlackfinTargetLowering:: isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const { // The Blackfin target isn't yet aware of offsets. diff --git a/lib/Target/Blackfin/BlackfinISelLowering.h b/lib/Target/Blackfin/BlackfinISelLowering.h index 9a54557..b65775b 100644 --- a/lib/Target/Blackfin/BlackfinISelLowering.h +++ b/lib/Target/Blackfin/BlackfinISelLowering.h @@ -48,9 +48,6 @@ namespace llvm { std::pair getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const; - std::vector - getRegClassForInlineAsmConstraint(const std::string &Constraint, - EVT VT) const; virtual bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const; const char *getTargetNodeName(unsigned Opcode) const; diff --git a/lib/Target/Blackfin/BlackfinRegisterInfo.td b/lib/Target/Blackfin/BlackfinRegisterInfo.td index 0d502fd..1c42205 100644 --- a/lib/Target/Blackfin/BlackfinRegisterInfo.td +++ b/lib/Target/Blackfin/BlackfinRegisterInfo.td @@ -261,3 +261,17 @@ def StatBit : RegisterClass<"BF", [i1], 8, // Should be i40, but that isn't defined. It is not a legal type yet anyway. def Accu : RegisterClass<"BF", [i64], 64, (add A0, A1)>; + +// Register classes to match inline asm constraints. +def zCons : RegisterClass<"BF", [i32], 32, (add P0, P1, P2)>; +def DCons : RegisterClass<"BF", [i32], 32, (add R0, R2, R4, R6)>; +def WCons : RegisterClass<"BF", [i32], 32, (add R1, R3, R5, R7)>; +def cCons : RegisterClass<"BF", [i32], 32, (add I0, I1, I2, I3, + B0, B1, B2, B3, + L0, L1, L2, L3)>; +def tCons : RegisterClass<"BF", [i32], 32, (add LT0, LT1)>; +def uCons : RegisterClass<"BF", [i32], 32, (add LB0, LB1)>; +def kCons : RegisterClass<"BF", [i32], 32, (add LC0, LC1)>; +def yCons : RegisterClass<"BF", [i32], 32, (add RETS, RETN, RETI, RETX, + RETE, ASTAT, SEQSTAT, + USP)>; -- cgit v1.1 From 38d642652320ae84bfd948ab1bfc2fd4b8399bba Mon Sep 17 00:00:00 2001 From: Eric Christopher Date: Wed, 29 Jun 2011 19:33:04 +0000 Subject: Update comment for getRegForInlineAsmConstraint for Mips. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134087 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Mips/MipsISelLowering.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index 8bd7e75..9e47a38 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -2329,9 +2329,9 @@ MipsTargetLowering::getSingleConstraintMatchWeight( return weight; } -/// getRegClassForInlineAsmConstraint - Given a constraint letter (e.g. "r"), -/// return a list of registers that can be used to satisfy the constraint. -/// This should only be used for C_RegisterClass constraints. +/// Given a register class constraint, like 'r', if this corresponds directly +/// to an LLVM register class, return a register of 0 and the register class +/// pointer. std::pair MipsTargetLowering:: getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const { -- cgit v1.1 From 46b65f7a2bdd685e0d3af0bc33296be2d2f182aa Mon Sep 17 00:00:00 2001 From: Eric Christopher Date: Wed, 29 Jun 2011 19:40:01 +0000 Subject: Move Alpha from getRegClassForInlineAsmConstraint to getRegForInlineAsmConstraint. Part of rdar://9643582 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134088 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Alpha/AlphaISelLowering.cpp | 40 ++++++++++------------------------ lib/Target/Alpha/AlphaISelLowering.h | 6 ++--- 2 files changed, 14 insertions(+), 32 deletions(-) diff --git a/lib/Target/Alpha/AlphaISelLowering.cpp b/lib/Target/Alpha/AlphaISelLowering.cpp index 0875cfd..54433a4 100644 --- a/lib/Target/Alpha/AlphaISelLowering.cpp +++ b/lib/Target/Alpha/AlphaISelLowering.cpp @@ -824,41 +824,23 @@ AlphaTargetLowering::getSingleConstraintMatchWeight( return weight; } -std::vector AlphaTargetLowering:: -getRegClassForInlineAsmConstraint(const std::string &Constraint, - EVT VT) const { +/// Given a register class constraint, like 'r', if this corresponds directly +/// to an LLVM register class, return a register of 0 and the register class +/// pointer. +std::pair AlphaTargetLowering:: +getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const +{ if (Constraint.size() == 1) { switch (Constraint[0]) { - default: break; // Unknown constriant letter - case 'f': - return make_vector(Alpha::F0 , Alpha::F1 , Alpha::F2 , - Alpha::F3 , Alpha::F4 , Alpha::F5 , - Alpha::F6 , Alpha::F7 , Alpha::F8 , - Alpha::F9 , Alpha::F10, Alpha::F11, - Alpha::F12, Alpha::F13, Alpha::F14, - Alpha::F15, Alpha::F16, Alpha::F17, - Alpha::F18, Alpha::F19, Alpha::F20, - Alpha::F21, Alpha::F22, Alpha::F23, - Alpha::F24, Alpha::F25, Alpha::F26, - Alpha::F27, Alpha::F28, Alpha::F29, - Alpha::F30, Alpha::F31, 0); case 'r': - return make_vector(Alpha::R0 , Alpha::R1 , Alpha::R2 , - Alpha::R3 , Alpha::R4 , Alpha::R5 , - Alpha::R6 , Alpha::R7 , Alpha::R8 , - Alpha::R9 , Alpha::R10, Alpha::R11, - Alpha::R12, Alpha::R13, Alpha::R14, - Alpha::R15, Alpha::R16, Alpha::R17, - Alpha::R18, Alpha::R19, Alpha::R20, - Alpha::R21, Alpha::R22, Alpha::R23, - Alpha::R24, Alpha::R25, Alpha::R26, - Alpha::R27, Alpha::R28, Alpha::R29, - Alpha::R30, Alpha::R31, 0); + return std::make_pair(0U, Alpha::GPRCRegisterClass); + case 'f': + return std::make_pair(0U, Alpha::F4RCRegisterClass); } } - - return std::vector(); + return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT); } + //===----------------------------------------------------------------------===// // Other Lowering Code //===----------------------------------------------------------------------===// diff --git a/lib/Target/Alpha/AlphaISelLowering.h b/lib/Target/Alpha/AlphaISelLowering.h index d38c314..13383f4 100644 --- a/lib/Target/Alpha/AlphaISelLowering.h +++ b/lib/Target/Alpha/AlphaISelLowering.h @@ -94,9 +94,9 @@ namespace llvm { ConstraintWeight getSingleConstraintMatchWeight( AsmOperandInfo &info, const char *constraint) const; - std::vector - getRegClassForInlineAsmConstraint(const std::string &Constraint, - EVT VT) const; + std::pair + getRegForInlineAsmConstraint(const std::string &Constraint, + EVT VT) const; MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr *MI, -- cgit v1.1 From 1e965641dc580b7910b7f1e318f15ddf2343b990 Mon Sep 17 00:00:00 2001 From: Eric Christopher Date: Wed, 29 Jun 2011 19:41:27 +0000 Subject: Add a TODO for the Alpha port inline asm constraints. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134089 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Alpha/AlphaISelLowering.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/Target/Alpha/AlphaISelLowering.cpp b/lib/Target/Alpha/AlphaISelLowering.cpp index 54433a4..e8aaf35 100644 --- a/lib/Target/Alpha/AlphaISelLowering.cpp +++ b/lib/Target/Alpha/AlphaISelLowering.cpp @@ -835,6 +835,8 @@ getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const case 'r': return std::make_pair(0U, Alpha::GPRCRegisterClass); case 'f': + // TODO: Do we need to add the 64-bit register class here when + // it contains the same registers? return std::make_pair(0U, Alpha::F4RCRegisterClass); } } -- cgit v1.1 From 74472b4bf963c424da04f42dffdb94c85ef964bc Mon Sep 17 00:00:00 2001 From: Jim Grosbach Date: Wed, 29 Jun 2011 20:26:39 +0000 Subject: Refactor away tSpill and tRestore pseudos in ARM backend. The tSpill and tRestore instructions are just copies of the tSTRspi and tLDRspi instructions, respectively. Just use those directly instead. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134092 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMBaseInstrInfo.cpp | 4 ++-- lib/Target/ARM/ARMInstrThumb.td | 26 -------------------------- lib/Target/ARM/Thumb1FrameLowering.cpp | 2 +- lib/Target/ARM/Thumb1InstrInfo.cpp | 4 ++-- lib/Target/ARM/Thumb1RegisterInfo.cpp | 8 +++----- utils/TableGen/ARMDecoderEmitter.cpp | 4 +--- 6 files changed, 9 insertions(+), 39 deletions(-) diff --git a/lib/Target/ARM/ARMBaseInstrInfo.cpp b/lib/Target/ARM/ARMBaseInstrInfo.cpp index 6a6ba92..9f56637 100644 --- a/lib/Target/ARM/ARMBaseInstrInfo.cpp +++ b/lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -792,7 +792,7 @@ ARMBaseInstrInfo::isStoreToStackSlot(const MachineInstr *MI, break; case ARM::STRi12: case ARM::t2STRi12: - case ARM::tSpill: + case ARM::tSTRspi: case ARM::VSTRD: case ARM::VSTRS: if (MI->getOperand(1).isFI() && @@ -927,7 +927,7 @@ ARMBaseInstrInfo::isLoadFromStackSlot(const MachineInstr *MI, break; case ARM::LDRi12: case ARM::t2LDRi12: - case ARM::tRestore: + case ARM::tLDRspi: case ARM::VLDRD: case ARM::VLDRS: if (MI->getOperand(1).isFI() && diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td index 328d330..735f3e9 100644 --- a/lib/Target/ARM/ARMInstrThumb.td +++ b/lib/Target/ARM/ARMInstrThumb.td @@ -686,19 +686,6 @@ def tLDRspi : T1pIs<(outs tGPR:$Rt), (ins t_addrmode_sp:$addr), IIC_iLoad_i, let Inst{7-0} = addr; } -// Special instruction for restore. It cannot clobber condition register -// when it's expanded by eliminateCallFramePseudoInstr(). -let canFoldAsLoad = 1, mayLoad = 1, neverHasSideEffects = 1 in -// FIXME: Pseudo for tLDRspi -def tRestore : T1pIs<(outs tGPR:$dst), (ins t_addrmode_sp:$addr), IIC_iLoad_i, - "ldr", "\t$dst, $addr", []>, - T1LdStSP<{1,?,?}> { - bits<3> Rt; - bits<8> addr; - let Inst{10-8} = Rt; - let Inst{7-0} = addr; -} - // Load tconstpool // FIXME: Use ldr.n to work around a Darwin assembler bug. let canFoldAsLoad = 1, isReMaterializable = 1 in @@ -755,19 +742,6 @@ def tSTRspi : T1pIs<(outs), (ins tGPR:$Rt, t_addrmode_sp:$addr), IIC_iStore_i, let Inst{7-0} = addr; } -let mayStore = 1, neverHasSideEffects = 1 in -// Special instruction for spill. It cannot clobber condition register when it's -// expanded by eliminateCallFramePseudoInstr(). -// FIXME: Pseudo for tSTRspi -def tSpill : T1pIs<(outs), (ins tGPR:$src, t_addrmode_sp:$addr), IIC_iStore_i, - "str", "\t$src, $addr", []>, - T1LdStSP<{0,?,?}> { - bits<3> Rt; - bits<8> addr; - let Inst{10-8} = Rt; - let Inst{7-0} = addr; -} - //===----------------------------------------------------------------------===// // Load / store multiple Instructions. // diff --git a/lib/Target/ARM/Thumb1FrameLowering.cpp b/lib/Target/ARM/Thumb1FrameLowering.cpp index e56d481..80b57c9 100644 --- a/lib/Target/ARM/Thumb1FrameLowering.cpp +++ b/lib/Target/ARM/Thumb1FrameLowering.cpp @@ -177,7 +177,7 @@ static bool isCalleeSavedRegister(unsigned Reg, const unsigned *CSRegs) { } static bool isCSRestore(MachineInstr *MI, const unsigned *CSRegs) { - if (MI->getOpcode() == ARM::tRestore && + if (MI->getOpcode() == ARM::tLDRspi && MI->getOperand(1).isFI() && isCalleeSavedRegister(MI->getOperand(0).getReg(), CSRegs)) return true; diff --git a/lib/Target/ARM/Thumb1InstrInfo.cpp b/lib/Target/ARM/Thumb1InstrInfo.cpp index b430ab3..e5d3a89 100644 --- a/lib/Target/ARM/Thumb1InstrInfo.cpp +++ b/lib/Target/ARM/Thumb1InstrInfo.cpp @@ -75,7 +75,7 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, MachineMemOperand::MOStore, MFI.getObjectSize(FI), MFI.getObjectAlignment(FI)); - AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::tSpill)) + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::tSTRspi)) .addReg(SrcReg, getKillRegState(isKill)) .addFrameIndex(FI).addImm(0).addMemOperand(MMO)); } @@ -104,7 +104,7 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, MachineMemOperand::MOLoad, MFI.getObjectSize(FI), MFI.getObjectAlignment(FI)); - AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::tRestore), DestReg) + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::tLDRspi), DestReg) .addFrameIndex(FI).addImm(0).addMemOperand(MMO)); } } diff --git a/lib/Target/ARM/Thumb1RegisterInfo.cpp b/lib/Target/ARM/Thumb1RegisterInfo.cpp index 2a1dbf7..c485c8e 100644 --- a/lib/Target/ARM/Thumb1RegisterInfo.cpp +++ b/lib/Target/ARM/Thumb1RegisterInfo.cpp @@ -377,11 +377,9 @@ static void removeOperands(MachineInstr &MI, unsigned i) { static unsigned convertToNonSPOpcode(unsigned Opcode) { switch (Opcode) { case ARM::tLDRspi: - case ARM::tRestore: // FIXME: Should this opcode be here? return ARM::tLDRi; case ARM::tSTRspi: - case ARM::tSpill: // FIXME: Should this opcode be here? return ARM::tSTRi; } @@ -524,7 +522,7 @@ rewriteFrameIndex(MachineBasicBlock::iterator II, unsigned FrameRegIdx, // If this is a thumb spill / restore, we will be using a constpool load to // materialize the offset. - if (Opcode == ARM::tRestore || Opcode == ARM::tSpill) { + if (Opcode == ARM::tLDRspi || Opcode == ARM::tSTRspi) { ImmOp.ChangeToImmediate(0); } else { // Otherwise, it didn't fit. Pull in what we can to simplify the immed. @@ -664,7 +662,7 @@ Thumb1RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, // Use the destination register to materialize sp + offset. unsigned TmpReg = MI.getOperand(0).getReg(); bool UseRR = false; - if (Opcode == ARM::tRestore) { + if (Opcode == ARM::tLDRspi) { if (FrameReg == ARM::SP) emitThumbRegPlusImmInReg(MBB, II, dl, TmpReg, FrameReg, Offset, false, TII, *this); @@ -687,7 +685,7 @@ Thumb1RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, VReg = MF.getRegInfo().createVirtualRegister(ARM::tGPRRegisterClass); bool UseRR = false; - if (Opcode == ARM::tSpill) { + if (Opcode == ARM::tSTRspi) { if (FrameReg == ARM::SP) emitThumbRegPlusImmInReg(MBB, II, dl, VReg, FrameReg, Offset, false, TII, *this); diff --git a/utils/TableGen/ARMDecoderEmitter.cpp b/utils/TableGen/ARMDecoderEmitter.cpp index 62bd1c6..cccfefd 100644 --- a/utils/TableGen/ARMDecoderEmitter.cpp +++ b/utils/TableGen/ARMDecoderEmitter.cpp @@ -1667,14 +1667,12 @@ ARMDEBackend::populateInstruction(const CodeGenInstruction &CGI, // tPOP_RET/t2LDMIA_RET conflict with tPOP/t2LDM (ditto) // tMOVCCi conflicts with tMOVi8 // tMOVCCr conflicts with tMOVgpr2gpr - // tSpill conflicts with tSTRspi // tLDRcp conflicts with tLDRspi - // tRestore conflicts with tLDRspi // t2MOVCCi16 conflicts with tMOVi16 if (Name == "tBfar" || Name == "tPOP_RET" || Name == "t2LDMIA_RET" || Name == "tMOVCCi" || Name == "tMOVCCr" || - Name == "tSpill" || Name == "tLDRcp" || Name == "tRestore" || + Name == "tLDRcp" || Name == "t2MOVCCi16") return false; } -- cgit v1.1 From 00258d17cd7152237141648d26e1b096cf0e882b Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Wed, 29 Jun 2011 20:55:48 +0000 Subject: make compose and isMoveInstr static functions. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134093 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/RegisterCoalescer.cpp | 19 ++++++++++--------- lib/CodeGen/RegisterCoalescer.h | 7 ------- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/lib/CodeGen/RegisterCoalescer.cpp b/lib/CodeGen/RegisterCoalescer.cpp index 8826df4..3b8a3e8 100644 --- a/lib/CodeGen/RegisterCoalescer.cpp +++ b/lib/CodeGen/RegisterCoalescer.cpp @@ -90,15 +90,15 @@ INITIALIZE_PASS_END(RegisterCoalescer, "simple-register-coalescing", char RegisterCoalescer::ID = 0; -unsigned CoalescerPair::compose(unsigned a, unsigned b) const { +static unsigned compose(const TargetRegisterInfo &tri, unsigned a, unsigned b) { if (!a) return b; if (!b) return a; - return tri_.composeSubRegIndices(a, b); + return tri.composeSubRegIndices(a, b); } -bool CoalescerPair::isMoveInstr(const MachineInstr *MI, - unsigned &Src, unsigned &Dst, - unsigned &SrcSub, unsigned &DstSub) const { +static bool isMoveInstr(const TargetRegisterInfo &tri, const MachineInstr *MI, + unsigned &Src, unsigned &Dst, + unsigned &SrcSub, unsigned &DstSub) { if (MI->isCopy()) { Dst = MI->getOperand(0).getReg(); DstSub = MI->getOperand(0).getSubReg(); @@ -106,7 +106,8 @@ bool CoalescerPair::isMoveInstr(const MachineInstr *MI, SrcSub = MI->getOperand(1).getSubReg(); } else if (MI->isSubregToReg()) { Dst = MI->getOperand(0).getReg(); - DstSub = compose(MI->getOperand(0).getSubReg(), MI->getOperand(3).getImm()); + DstSub = compose(tri, MI->getOperand(0).getSubReg(), + MI->getOperand(3).getImm()); Src = MI->getOperand(2).getReg(); SrcSub = MI->getOperand(2).getSubReg(); } else @@ -120,7 +121,7 @@ bool CoalescerPair::setRegisters(const MachineInstr *MI) { flipped_ = crossClass_ = false; unsigned Src, Dst, SrcSub, DstSub; - if (!isMoveInstr(MI, Src, Dst, SrcSub, DstSub)) + if (!isMoveInstr(tri_, MI, Src, Dst, SrcSub, DstSub)) return false; partial_ = SrcSub || DstSub; @@ -210,7 +211,7 @@ bool CoalescerPair::isCoalescable(const MachineInstr *MI) const { if (!MI) return false; unsigned Src, Dst, SrcSub, DstSub; - if (!isMoveInstr(MI, Src, Dst, SrcSub, DstSub)) + if (!isMoveInstr(tri_, MI, Src, Dst, SrcSub, DstSub)) return false; // Find the virtual register that is srcReg_. @@ -239,7 +240,7 @@ bool CoalescerPair::isCoalescable(const MachineInstr *MI) const { if (dstReg_ != Dst) return false; // Registers match, do the subregisters line up? - return compose(subIdx_, SrcSub) == DstSub; + return compose(tri_, subIdx_, SrcSub) == DstSub; } } diff --git a/lib/CodeGen/RegisterCoalescer.h b/lib/CodeGen/RegisterCoalescer.h index 2e8a8ae..f06675a 100644 --- a/lib/CodeGen/RegisterCoalescer.h +++ b/lib/CodeGen/RegisterCoalescer.h @@ -281,13 +281,6 @@ namespace llvm { /// is a physreg. const TargetRegisterClass *newRC_; - /// compose - Compose subreg indices a and b, either may be 0. - unsigned compose(unsigned, unsigned) const; - - /// isMoveInstr - Return true if MI is a move or subreg instruction. - bool isMoveInstr(const MachineInstr *MI, unsigned &Src, unsigned &Dst, - unsigned &SrcSub, unsigned &DstSub) const; - public: CoalescerPair(const TargetInstrInfo &tii, const TargetRegisterInfo &tri) : tii_(tii), tri_(tri), dstReg_(0), srcReg_(0), subIdx_(0), -- cgit v1.1 From 50cf9b38dc23d76eb8f6396c1d08b42ae1f5745b Mon Sep 17 00:00:00 2001 From: Eric Christopher Date: Wed, 29 Jun 2011 21:05:54 +0000 Subject: Remove todo. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134094 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Alpha/AlphaISelLowering.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/Target/Alpha/AlphaISelLowering.cpp b/lib/Target/Alpha/AlphaISelLowering.cpp index e8aaf35..54433a4 100644 --- a/lib/Target/Alpha/AlphaISelLowering.cpp +++ b/lib/Target/Alpha/AlphaISelLowering.cpp @@ -835,8 +835,6 @@ getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const case 'r': return std::make_pair(0U, Alpha::GPRCRegisterClass); case 'f': - // TODO: Do we need to add the 64-bit register class here when - // it contains the same registers? return std::make_pair(0U, Alpha::F4RCRegisterClass); } } -- cgit v1.1 From fa6f5917af0ee34e6a8d6d6eaffe89024d5d7a04 Mon Sep 17 00:00:00 2001 From: Eric Christopher Date: Wed, 29 Jun 2011 21:10:36 +0000 Subject: Remove getRegClassForInlineAsmConstraint from the ARM port. Part of rdar://9643582 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134095 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMISelLowering.cpp | 71 ++++++++------------------------------ lib/Target/ARM/ARMISelLowering.h | 3 -- 2 files changed, 15 insertions(+), 59 deletions(-) diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index b0425f1..507cc60 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -5526,7 +5526,7 @@ SDValue combineSelectAndUse(SDNode *N, SDValue Slct, SDValue OtherOp, return SDValue(); } -// AddCombineToVPADDL- For pair-wise add on neon, use the vpaddl instruction +// AddCombineToVPADDL- For pair-wise add on neon, use the vpaddl instruction // (only after legalization). static SDValue AddCombineToVPADDL(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, @@ -5557,25 +5557,25 @@ static SDValue AddCombineToVPADDL(SDNode *N, SDValue N0, SDValue N1, SDNode *V = Vec.getNode(); unsigned nextIndex = 0; - // For each operands to the ADD which are BUILD_VECTORs, + // For each operands to the ADD which are BUILD_VECTORs, // check to see if each of their operands are an EXTRACT_VECTOR with // the same vector and appropriate index. for (unsigned i = 0, e = N0->getNumOperands(); i != e; ++i) { if (N0->getOperand(i)->getOpcode() == ISD::EXTRACT_VECTOR_ELT && N1->getOperand(i)->getOpcode() == ISD::EXTRACT_VECTOR_ELT) { - + SDValue ExtVec0 = N0->getOperand(i); SDValue ExtVec1 = N1->getOperand(i); - + // First operand is the vector, verify its the same. if (V != ExtVec0->getOperand(0).getNode() || V != ExtVec1->getOperand(0).getNode()) return SDValue(); - + // Second is the constant, verify its correct. ConstantSDNode *C0 = dyn_cast(ExtVec0->getOperand(1)); ConstantSDNode *C1 = dyn_cast(ExtVec1->getOperand(1)); - + // For the constant, we want to see all the even or all the odd. if (!C0 || !C1 || C0->getZExtValue() != nextIndex || C1->getZExtValue() != nextIndex+1) @@ -5583,7 +5583,7 @@ static SDValue AddCombineToVPADDL(SDNode *N, SDValue N0, SDValue N1, // Increment index. nextIndex+=2; - } else + } else return SDValue(); } @@ -5598,7 +5598,7 @@ static SDValue AddCombineToVPADDL(SDNode *N, SDValue N0, SDValue N1, // Input is the vector. Ops.push_back(Vec); - + // Get widened type and narrowed type. MVT widenType; unsigned numElem = VT.getVectorNumElements(); @@ -5627,7 +5627,7 @@ static SDValue PerformADDCombineWithOperands(SDNode *N, SDValue N0, SDValue N1, SDValue Result = AddCombineToVPADDL(N, N0, N1, DCI, Subtarget); if (Result.getNode()) return Result; - + // fold (add (select cc, 0, c), x) -> (select cc, x, (add, x, c)) if (N0.getOpcode() == ISD::SELECT && N0.getNode()->hasOneUse()) { SDValue Result = combineSelectAndUse(N, N0, N1, DCI); @@ -6482,7 +6482,7 @@ static SDValue PerformVDUPLANECombine(SDNode *N, return DCI.DAG.getNode(ISD::BITCAST, N->getDebugLoc(), VT, Op); } -// isConstVecPow2 - Return true if each vector element is a power of 2, all +// isConstVecPow2 - Return true if each vector element is a power of 2, all // elements are the same constant, C, and Log2(C) ranges from 1 to 32. static bool isConstVecPow2(SDValue ConstVec, bool isSigned, uint64_t &C) { @@ -6494,7 +6494,7 @@ static bool isConstVecPow2(SDValue ConstVec, bool isSigned, uint64_t &C) if (!C) return false; - bool isExact; + bool isExact; APFloat APF = C->getValueAPF(); if (APF.convertToInteger(&cN, 64, isSigned, APFloat::rmTowardZero, &isExact) != APFloat::opOK || !isExact) @@ -6532,7 +6532,7 @@ static SDValue PerformVCVTCombine(SDNode *N, SDValue ConstVec = Op->getOperand(1); bool isSigned = N->getOpcode() == ISD::FP_TO_SINT; - if (ConstVec.getOpcode() != ISD::BUILD_VECTOR || + if (ConstVec.getOpcode() != ISD::BUILD_VECTOR || !isConstVecPow2(ConstVec, isSigned, C)) return SDValue(); @@ -6540,7 +6540,7 @@ static SDValue PerformVCVTCombine(SDNode *N, Intrinsic::arm_neon_vcvtfp2fxu; return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, N->getDebugLoc(), N->getValueType(0), - DAG.getConstant(IntrinsicOpcode, MVT::i32), N0, + DAG.getConstant(IntrinsicOpcode, MVT::i32), N0, DAG.getConstant(Log2_64(C), MVT::i32)); } @@ -6572,11 +6572,11 @@ static SDValue PerformVDIVCombine(SDNode *N, !isConstVecPow2(ConstVec, isSigned, C)) return SDValue(); - unsigned IntrinsicOpcode = isSigned ? Intrinsic::arm_neon_vcvtfxs2fp : + unsigned IntrinsicOpcode = isSigned ? Intrinsic::arm_neon_vcvtfxs2fp : Intrinsic::arm_neon_vcvtfxu2fp; return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, N->getDebugLoc(), Op.getValueType(), - DAG.getConstant(IntrinsicOpcode, MVT::i32), + DAG.getConstant(IntrinsicOpcode, MVT::i32), Op.getOperand(0), DAG.getConstant(Log2_64(C), MVT::i32)); } @@ -7556,47 +7556,6 @@ ARMTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint, return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT); } -std::vector ARMTargetLowering:: -getRegClassForInlineAsmConstraint(const std::string &Constraint, - EVT VT) const { - if (Constraint.size() != 1) - return std::vector(); - - switch (Constraint[0]) { // GCC ARM Constraint Letters - default: break; - case 'l': - return make_vector(ARM::R0, ARM::R1, ARM::R2, ARM::R3, - ARM::R4, ARM::R5, ARM::R6, ARM::R7, - 0); - case 'r': - return make_vector(ARM::R0, ARM::R1, ARM::R2, ARM::R3, - ARM::R4, ARM::R5, ARM::R6, ARM::R7, - ARM::R8, ARM::R9, ARM::R10, ARM::R11, - ARM::R12, ARM::LR, 0); - case 'w': - if (VT == MVT::f32) - return make_vector(ARM::S0, ARM::S1, ARM::S2, ARM::S3, - ARM::S4, ARM::S5, ARM::S6, ARM::S7, - ARM::S8, ARM::S9, ARM::S10, ARM::S11, - ARM::S12,ARM::S13,ARM::S14,ARM::S15, - ARM::S16,ARM::S17,ARM::S18,ARM::S19, - ARM::S20,ARM::S21,ARM::S22,ARM::S23, - ARM::S24,ARM::S25,ARM::S26,ARM::S27, - ARM::S28,ARM::S29,ARM::S30,ARM::S31, 0); - if (VT.getSizeInBits() == 64) - return make_vector(ARM::D0, ARM::D1, ARM::D2, ARM::D3, - ARM::D4, ARM::D5, ARM::D6, ARM::D7, - ARM::D8, ARM::D9, ARM::D10,ARM::D11, - ARM::D12,ARM::D13,ARM::D14,ARM::D15, 0); - if (VT.getSizeInBits() == 128) - return make_vector(ARM::Q0, ARM::Q1, ARM::Q2, ARM::Q3, - ARM::Q4, ARM::Q5, ARM::Q6, ARM::Q7, 0); - break; - } - - return std::vector(); -} - /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops /// vector. If it is invalid, don't add anything to Ops. void ARMTargetLowering::LowerAsmOperandForConstraint(SDValue Op, diff --git a/lib/Target/ARM/ARMISelLowering.h b/lib/Target/ARM/ARMISelLowering.h index 21a9a3a..dd9df0e 100644 --- a/lib/Target/ARM/ARMISelLowering.h +++ b/lib/Target/ARM/ARMISelLowering.h @@ -306,9 +306,6 @@ namespace llvm { std::pair getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const; - std::vector - getRegClassForInlineAsmConstraint(const std::string &Constraint, - EVT VT) const; /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops /// vector. If it is invalid, don't add anything to Ops. If hasMemory is -- cgit v1.1 From 33b259f46cc281531c36b471862cb0853d2528df Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Wed, 29 Jun 2011 21:58:37 +0000 Subject: Indentation git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134100 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/MC/MCInstrInfo.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/llvm/MC/MCInstrInfo.h b/include/llvm/MC/MCInstrInfo.h index 9b15825..a63e5fa 100644 --- a/include/llvm/MC/MCInstrInfo.h +++ b/include/llvm/MC/MCInstrInfo.h @@ -25,7 +25,7 @@ namespace llvm { /// class MCInstrInfo { const MCInstrDesc *Desc; // Raw array to allow static init'n - unsigned NumOpcodes; // Number of entries in the desc array + unsigned NumOpcodes; // Number of entries in the desc array public: /// InitMCInstrInfo - Initialize MCInstrInfo, called by TableGen -- cgit v1.1 From ae218dee5e3a079becd6b9b8d47e67cf814b9b70 Mon Sep 17 00:00:00 2001 From: Jim Grosbach Date: Wed, 29 Jun 2011 22:01:15 +0000 Subject: ARM RSCS* don't need explicit TableGen decoder checks. They've been pseudos for a while now, so the decoder will never see them in the first place. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134101 91177308-0d34-0410-b5e6-96231b3b80d8 --- utils/TableGen/ARMDecoderEmitter.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/utils/TableGen/ARMDecoderEmitter.cpp b/utils/TableGen/ARMDecoderEmitter.cpp index cccfefd..a320e77 100644 --- a/utils/TableGen/ARMDecoderEmitter.cpp +++ b/utils/TableGen/ARMDecoderEmitter.cpp @@ -1592,10 +1592,6 @@ ARMDEBackend::populateInstruction(const CodeGenInstruction &CGI, // The following special cases are for conflict resolutions. // - // RSCSri and RSCSrs set the 's' bit, but are not predicated. We are - // better off using the generic RSCri and RSCrs instructions. - if (Name == "RSCSri" || Name == "RSCSrs") return false; - // A8-598: VEXT // Vector Extract extracts elements from the bottom end of the second // operand vector and the top end of the first, concatenates them and -- cgit v1.1 From faff12731968c2d3f1ff56a43749d27e1696aafa Mon Sep 17 00:00:00 2001 From: Cameron Zwarich Date: Wed, 29 Jun 2011 22:24:25 +0000 Subject: In the ARM global merging pass, allow extraneous alignment specifiers. This pass already makes the assumption, which is correct on ARM, that a type's alignment is less than its alloc size. This improves codegen with Clang (which inserts a lot of extraneous alignment specifiers) and fixes . git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134106 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMGlobalMerge.cpp | 6 ++++-- test/CodeGen/ARM/2011-06-29-MergeGlobalsAlign.ll | 12 ++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 test/CodeGen/ARM/2011-06-29-MergeGlobalsAlign.ll diff --git a/lib/Target/ARM/ARMGlobalMerge.cpp b/lib/Target/ARM/ARMGlobalMerge.cpp index 3f02383..4bdd4f1 100644 --- a/lib/Target/ARM/ARMGlobalMerge.cpp +++ b/lib/Target/ARM/ARMGlobalMerge.cpp @@ -175,7 +175,9 @@ bool ARMGlobalMerge::doInitialization(Module &M) { continue; // Ignore fancy-aligned globals for now. - if (I->getAlignment() != 0) + unsigned Alignment = I->getAlignment(); + unsigned AllocSize = TD->getTypeAllocSize(I->getType()->getElementType()); + if (Alignment > AllocSize) continue; // Ignore all 'special' globals. @@ -183,7 +185,7 @@ bool ARMGlobalMerge::doInitialization(Module &M) { I->getName().startswith(".llvm.")) continue; - if (TD->getTypeAllocSize(I->getType()->getElementType()) < MaxOffset) { + if (AllocSize < MaxOffset) { const TargetLoweringObjectFile &TLOF = TLI->getObjFileLowering(); if (TLOF.getKindForGlobal(I, TLI->getTargetMachine()).isBSSLocal()) BSSGlobals.push_back(I); diff --git a/test/CodeGen/ARM/2011-06-29-MergeGlobalsAlign.ll b/test/CodeGen/ARM/2011-06-29-MergeGlobalsAlign.ll new file mode 100644 index 0000000..1b5b8a9 --- /dev/null +++ b/test/CodeGen/ARM/2011-06-29-MergeGlobalsAlign.ll @@ -0,0 +1,12 @@ +; RUN: llc < %s -mtriple=thumbv7-apple-darwin10 | FileCheck %s +; CHECK: .zerofill __DATA,__bss,__MergedGlobals,16,2 + +%struct.config = type { i16, i16, i16, i16 } + +@prev = external global [0 x i16] +@max_lazy_match = internal unnamed_addr global i32 0, align 4 +@read_buf = external global i32 (i8*, i32)* +@window = external global [0 x i8] +@lookahead = internal unnamed_addr global i32 0, align 4 +@eofile.b = internal unnamed_addr global i1 false +@ins_h = internal unnamed_addr global i32 0, align 4 -- cgit v1.1 From 45f454d5691cc23584992974f4460728a02186c8 Mon Sep 17 00:00:00 2001 From: Andrew Trick Date: Wed, 29 Jun 2011 22:52:51 +0000 Subject: whitespace git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134110 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Support/IRBuilder.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/include/llvm/Support/IRBuilder.h b/include/llvm/Support/IRBuilder.h index 6a7c277..9058e3e 100644 --- a/include/llvm/Support/IRBuilder.h +++ b/include/llvm/Support/IRBuilder.h @@ -82,7 +82,7 @@ public: InsertPt = I; SetCurrentDebugLocation(I->getDebugLoc()); } - + /// SetInsertPoint - This specifies that created instructions should be /// inserted at the specified point. void SetInsertPoint(BasicBlock *TheBB, BasicBlock::iterator IP) { @@ -110,7 +110,7 @@ public: /// getCurrentFunctionReturnType - Get the return type of the current function /// that we're emitting into. const Type *getCurrentFunctionReturnType() const; - + /// InsertPoint - A saved insertion point. class InsertPoint { BasicBlock *Block; @@ -198,7 +198,7 @@ public: ConstantInt *getInt64(uint64_t C) { return ConstantInt::get(getInt64Ty(), C); } - + /// getInt - Get a constant integer value. ConstantInt *getInt(const APInt &AI) { return ConstantInt::get(Context, AI); @@ -263,7 +263,7 @@ public: bool isVolatile = false, MDNode *TBAATag = 0) { return CreateMemSet(Ptr, Val, getInt64(Size), Align, isVolatile, TBAATag); } - + CallInst *CreateMemSet(Value *Ptr, Value *Val, Value *Size, unsigned Align, bool isVolatile = false, MDNode *TBAATag = 0); @@ -274,7 +274,7 @@ public: bool isVolatile = false, MDNode *TBAATag = 0) { return CreateMemCpy(Dst, Src, getInt64(Size), Align, isVolatile, TBAATag); } - + CallInst *CreateMemCpy(Value *Dst, Value *Src, Value *Size, unsigned Align, bool isVolatile = false, MDNode *TBAATag = 0); @@ -285,9 +285,9 @@ public: bool isVolatile = false, MDNode *TBAATag = 0) { return CreateMemMove(Dst, Src, getInt64(Size), Align, isVolatile, TBAATag); } - + CallInst *CreateMemMove(Value *Dst, Value *Src, Value *Size, unsigned Align, - bool isVolatile = false, MDNode *TBAATag = 0); + bool isVolatile = false, MDNode *TBAATag = 0); /// CreateLifetimeStart - Create a lifetime.start intrinsic. If the pointer /// isn't i8* it will be converted. @@ -341,7 +341,7 @@ public: SetInsertPoint(IP); SetCurrentDebugLocation(IP->getDebugLoc()); } - + IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP, const T& F) : IRBuilderBase(TheBB->getContext()), Folder(F) { SetInsertPoint(TheBB, IP); -- cgit v1.1 From 3290239daff266dce1051dfd103106956e05a7b1 Mon Sep 17 00:00:00 2001 From: Andrew Trick Date: Wed, 29 Jun 2011 23:01:52 +0000 Subject: Added IRBuilder::SetInsertPoint(Use) to find a valid insertion point that dominates the given Use. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134111 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Support/IRBuilder.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/include/llvm/Support/IRBuilder.h b/include/llvm/Support/IRBuilder.h index 9058e3e..9459280 100644 --- a/include/llvm/Support/IRBuilder.h +++ b/include/llvm/Support/IRBuilder.h @@ -90,6 +90,19 @@ public: InsertPt = IP; } + /// SetInsertPoint(Use) - Find the nearest point that dominates this use, and + /// specify that created instructions should be inserted at this point. + void SetInsertPoint(Use &U) { + Instruction *UseInst = cast(U.getUser()); + if (PHINode *Phi = dyn_cast(UseInst)) { + BasicBlock *PredBB = Phi->getIncomingBlock(U); + assert(U != PredBB->getTerminator() && "critical edge not split"); + SetInsertPoint(PredBB, PredBB->getTerminator()); + return; + } + SetInsertPoint(UseInst); + } + /// SetCurrentDebugLocation - Set location information used by debugging /// information. void SetCurrentDebugLocation(const DebugLoc &L) { @@ -342,6 +355,12 @@ public: SetCurrentDebugLocation(IP->getDebugLoc()); } + explicit IRBuilder(Use &U) + : IRBuilderBase(U->getContext()), Folder() { + SetInsertPoint(U); + SetCurrentDebugLocation(cast(U.getUser())->getDebugLoc()); + } + IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP, const T& F) : IRBuilderBase(TheBB->getContext()), Folder(F) { SetInsertPoint(TheBB, IP); -- cgit v1.1 From cc359d9fa28a871b18d93da76fd9cf516499e39f Mon Sep 17 00:00:00 2001 From: Andrew Trick Date: Wed, 29 Jun 2011 23:03:57 +0000 Subject: indvars -disable-iv-rewrite: insert new trunc instructions carefully. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134112 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Scalar/IndVarSimplify.cpp | 34 +++++++++++++++---------- test/Transforms/IndVarSimplify/no-iv-rewrite.ll | 33 ++++++++++++++++++++++-- 2 files changed, 52 insertions(+), 15 deletions(-) diff --git a/lib/Transforms/Scalar/IndVarSimplify.cpp b/lib/Transforms/Scalar/IndVarSimplify.cpp index 919da35..2a3e472 100644 --- a/lib/Transforms/Scalar/IndVarSimplify.cpp +++ b/lib/Transforms/Scalar/IndVarSimplify.cpp @@ -609,8 +609,7 @@ protected: const SCEVAddRecExpr *GetWideRecurrence(Instruction *NarrowUse); - Instruction *WidenIVUse(Instruction *NarrowUse, - Instruction *NarrowDef, + Instruction *WidenIVUse(Use &NarrowDefUse, Instruction *NarrowDef, Instruction *WideDef); }; } // anonymous namespace @@ -724,9 +723,10 @@ static bool HoistStep(Instruction *IncV, Instruction *InsertPos, /// WidenIVUse - Determine whether an individual user of the narrow IV can be /// widened. If so, return the wide clone of the user. -Instruction *WidenIV::WidenIVUse(Instruction *NarrowUse, - Instruction *NarrowDef, +Instruction *WidenIV::WidenIVUse(Use &NarrowDefUse, Instruction *NarrowDef, Instruction *WideDef) { + Instruction *NarrowUse = cast(NarrowDefUse.getUser()); + // To be consistent with IVUsers, stop traversing the def-use chain at // inner-loop phis or post-loop phis. if (isa(NarrowUse) && LI->getLoopFor(NarrowUse->getParent()) != L) @@ -744,7 +744,7 @@ Instruction *WidenIV::WidenIVUse(Instruction *NarrowUse, unsigned IVWidth = SE->getTypeSizeInBits(WideType); if (CastWidth < IVWidth) { // The cast isn't as wide as the IV, so insert a Trunc. - IRBuilder<> Builder(NarrowUse); + IRBuilder<> Builder(NarrowDefUse); NewDef = Builder.CreateTrunc(WideDef, NarrowUse->getType()); } else { @@ -778,11 +778,15 @@ Instruction *WidenIV::WidenIVUse(Instruction *NarrowUse, // This user does not evaluate to a recurence after widening, so don't // follow it. Instead insert a Trunc to kill off the original use, // eventually isolating the original narrow IV so it can be removed. - IRBuilder<> Builder(NarrowUse); + IRBuilder<> Builder(NarrowDefUse); Value *Trunc = Builder.CreateTrunc(WideDef, NarrowDef->getType()); NarrowUse->replaceUsesOfWith(NarrowDef, Trunc); return 0; } + // We assume that block terminators are not SCEVable. + assert(NarrowUse != NarrowUse->getParent()->getTerminator() && + "can't split terminators"); + // Reuse the IV increment that SCEVExpander created as long as it dominates // NarrowUse. Instruction *WideUse = 0; @@ -876,20 +880,20 @@ PHINode *WidenIV::CreateWideIV(SCEVExpander &Rewriter) { NarrowIVUsers.push_back(std::make_pair(&UI.getUse(), WidePhi)); } while (!NarrowIVUsers.empty()) { - Use *NarrowDefUse; + Use *UsePtr; Instruction *WideDef; - tie(NarrowDefUse, WideDef) = NarrowIVUsers.pop_back_val(); + tie(UsePtr, WideDef) = NarrowIVUsers.pop_back_val(); + Use &NarrowDefUse = *UsePtr; // Process a def-use edge. This may replace the use, so don't hold a // use_iterator across it. - Instruction *NarrowDef = cast(NarrowDefUse->get()); - Instruction *NarrowUse = cast(NarrowDefUse->getUser()); - Instruction *WideUse = WidenIVUse(NarrowUse, NarrowDef, WideDef); + Instruction *NarrowDef = cast(NarrowDefUse.get()); + Instruction *WideUse = WidenIVUse(NarrowDefUse, NarrowDef, WideDef); // Follow all def-use edges from the previous narrow use. if (WideUse) { - for (Value::use_iterator UI = NarrowUse->use_begin(), - UE = NarrowUse->use_end(); UI != UE; ++UI) { + for (Value::use_iterator UI = NarrowDefUse.getUser()->use_begin(), + UE = NarrowDefUse.getUser()->use_end(); UI != UE; ++UI) { NarrowIVUsers.push_back(std::make_pair(&UI.getUse(), WideUse)); } } @@ -1051,6 +1055,10 @@ bool IndVarSimplify::isSimpleIVUser(Instruction *I, const Loop *L) { // Get the symbolic expression for this instruction. const SCEV *S = SE->getSCEV(I); + // We assume that terminators are not SCEVable. + assert((!S || I != I->getParent()->getTerminator()) && + "can't fold terminators"); + // Only consider affine recurrences. const SCEVAddRecExpr *AR = dyn_cast(S); if (AR && AR->getLoop() == L) diff --git a/test/Transforms/IndVarSimplify/no-iv-rewrite.ll b/test/Transforms/IndVarSimplify/no-iv-rewrite.ll index 462ff58..3395be2 100644 --- a/test/Transforms/IndVarSimplify/no-iv-rewrite.ll +++ b/test/Transforms/IndVarSimplify/no-iv-rewrite.ll @@ -153,8 +153,37 @@ loop: br i1 %cond, label %loop, label %exit exit: - br label %return + ret void +} -return: +define void @maxvisitor(i32 %limit, i32* %base) nounwind { +entry: br label %loop + +; CHECK: loop: +; CHECK: phi i64 +; CHECK: trunc +; CHECK: exit +loop: + %idx = phi i32 [ 0, %entry ], [ %idx.next, %loop.inc ] + %max = phi i32 [ 0, %entry ], [ %max.next, %loop.inc ] + %idxprom = sext i32 %idx to i64 + %adr = getelementptr inbounds i32* %base, i64 %idxprom + %val = load i32* %adr + %cmp19 = icmp sgt i32 %val, %max + br i1 %cmp19, label %if.then, label %if.else + +if.then: + br label %loop.inc + +if.else: + br label %loop.inc + +loop.inc: + %max.next = phi i32 [ %idx, %if.then ], [ %max, %if.else ] + %idx.next = add nsw i32 %idx, 1 + %cmp = icmp slt i32 %idx.next, %limit + br i1 %cmp, label %loop, label %exit + +exit: ret void } \ No newline at end of file -- cgit v1.1 From 6531bddb86149b7e5c888fc9209456356b9361c6 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Wed, 29 Jun 2011 23:11:39 +0000 Subject: Always adjust the stack pointer immediately after the call. Some x86-32 calls pop values off the stack, and we need to readjust the stack pointer after the call. This happens when ADJCALLSTACKUP is eliminated. It could happen that spill code was inserted between the CALL and ADJCALLSTACKUP instructions, and we would compute wrong stack pointer offsets for those frame index references. Fix this by inserting the stack pointer adjustment immediately after the call instead of where the ADJCALLSTACKUP instruction was erased. I don't have a test case since we don't currently insert code in that position. We will soon, though. I am testing a regalloc patch that didn't work on Linux because of this. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134113 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86RegisterInfo.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/Target/X86/X86RegisterInfo.cpp b/lib/Target/X86/X86RegisterInfo.cpp index 90b333f..c0ce81a 100644 --- a/lib/Target/X86/X86RegisterInfo.cpp +++ b/lib/Target/X86/X86RegisterInfo.cpp @@ -662,6 +662,13 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, // The EFLAGS implicit def is dead. New->getOperand(3).setIsDead(); + + // We are not tracking the stack pointer adjustment by the callee, so make + // sure we restore the stack pointer immediately after the call, there may + // be spill code inserted between the CALL and ADJCALLSTACKUP instructions. + MachineBasicBlock::iterator B = MBB.begin(); + while (I != B && !llvm::prior(I)->getDesc().isCall()) + --I; MBB.insert(I, New); } } -- cgit v1.1 From f6fd90910a552ad9883f031350ae517e26dfdb44 Mon Sep 17 00:00:00 2001 From: Jim Grosbach Date: Wed, 29 Jun 2011 23:25:04 +0000 Subject: Remove redundant Thumb2 ADD/SUB SP instruction definitions. Unlike Thumb1, Thumb2 does not have dedicated encodings for adjusting the stack pointer. It can just use the normal add-register-immediate encoding since it can use all registers as a source, not just R0-R7. The extra instruction definitions are just duplicates of the normal instructions with the (not well enforced) constraint that the source register was SP. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134114 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMAsmPrinter.cpp | 12 +----- lib/Target/ARM/ARMBaseRegisterInfo.cpp | 4 -- lib/Target/ARM/ARMInstrThumb2.td | 57 ------------------------- lib/Target/ARM/ARMLoadStoreOptimizer.cpp | 12 +----- lib/Target/ARM/Thumb2InstrInfo.cpp | 10 ++--- lib/Target/ARM/Thumb2SizeReduction.cpp | 73 ++++++++++++++++++++------------ utils/TableGen/ARMDecoderEmitter.cpp | 6 +-- 7 files changed, 56 insertions(+), 118 deletions(-) diff --git a/lib/Target/ARM/ARMAsmPrinter.cpp b/lib/Target/ARM/ARMAsmPrinter.cpp index eb73902..4059560 100644 --- a/lib/Target/ARM/ARMAsmPrinter.cpp +++ b/lib/Target/ARM/ARMAsmPrinter.cpp @@ -1018,11 +1018,10 @@ void ARMAsmPrinter::EmitUnwindingInstruction(const MachineInstr *MI) { Offset = -MI->getOperand(2).getImm(); break; case ARM::SUBri: - case ARM::t2SUBrSPi: - Offset = MI->getOperand(2).getImm(); + Offset = MI->getOperand(2).getImm(); break; case ARM::tSUBspi: - Offset = MI->getOperand(2).getImm()*4; + Offset = MI->getOperand(2).getImm()*4; break; case ARM::tADDspi: case ARM::tADDrSPi: @@ -1097,13 +1096,6 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { OutStreamer.EmitInstruction(TmpInst); return; } - case ARM::t2ADDrSPi: - case ARM::t2ADDrSPi12: - case ARM::t2SUBrSPi: - case ARM::t2SUBrSPi12: - assert ((MI->getOperand(1).getReg() == ARM::SP) && - "Unexpected source register!"); - break; case ARM::t2MOVi32imm: assert(0 && "Should be lowered by thumb2it pass"); case ARM::DBG_VALUE: { diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/lib/Target/ARM/ARMBaseRegisterInfo.cpp index f231089..e46082d 100644 --- a/lib/Target/ARM/ARMBaseRegisterInfo.cpp +++ b/lib/Target/ARM/ARMBaseRegisterInfo.cpp @@ -1284,9 +1284,5 @@ ARMBaseRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, } // Update the original instruction to use the scratch register. MI.getOperand(i).ChangeToRegister(ScratchReg, false, false, true); - if (MI.getOpcode() == ARM::t2ADDrSPi) - MI.setDesc(TII.get(ARM::t2ADDri)); - else if (MI.getOpcode() == ARM::t2SUBrSPi) - MI.setDesc(TII.get(ARM::t2SUBri)); } } diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td index 06c63e3..95475bb 100644 --- a/lib/Target/ARM/ARMInstrThumb2.td +++ b/lib/Target/ARM/ARMInstrThumb2.td @@ -1169,63 +1169,6 @@ def t2LEApcrelJT : t2PseudoInst<(outs rGPR:$Rd), []>; -// FIXME: None of these add/sub SP special instructions should be necessary -// at all for thumb2 since they use the same encodings as the generic -// add/sub instructions. In thumb1 we need them since they have dedicated -// encodings. At the least, they should be pseudo instructions. -// ADD r, sp, {so_imm|i12} -let isCodeGenOnly = 1 in { -def t2ADDrSPi : T2sTwoRegImm<(outs GPR:$Rd), (ins GPR:$Rn, t2_so_imm:$imm), - IIC_iALUi, "add", ".w\t$Rd, $Rn, $imm", []> { - let Inst{31-27} = 0b11110; - let Inst{25} = 0; - let Inst{24-21} = 0b1000; - let Inst{15} = 0; -} -def t2ADDrSPi12 : T2TwoRegImm<(outs GPR:$Rd), (ins GPR:$Rn, imm0_4095:$imm), - IIC_iALUi, "addw", "\t$Rd, $Rn, $imm", []> { - let Inst{31-27} = 0b11110; - let Inst{25-20} = 0b100000; - let Inst{15} = 0; -} - -// ADD r, sp, so_reg -def t2ADDrSPs : T2sTwoRegShiftedReg< - (outs GPR:$Rd), (ins GPR:$Rn, t2_so_reg:$ShiftedRm), - IIC_iALUsi, "add", ".w\t$Rd, $Rn, $ShiftedRm", []> { - let Inst{31-27} = 0b11101; - let Inst{26-25} = 0b01; - let Inst{24-21} = 0b1000; - let Inst{15} = 0; -} - -// SUB r, sp, {so_imm|i12} -def t2SUBrSPi : T2sTwoRegImm<(outs GPR:$Rd), (ins GPR:$Rn, t2_so_imm:$imm), - IIC_iALUi, "sub", ".w\t$Rd, $Rn, $imm", []> { - let Inst{31-27} = 0b11110; - let Inst{25} = 0; - let Inst{24-21} = 0b1101; - let Inst{15} = 0; -} -def t2SUBrSPi12 : T2TwoRegImm<(outs GPR:$Rd), (ins GPR:$Rn, imm0_4095:$imm), - IIC_iALUi, "subw", "\t$Rd, $Rn, $imm", []> { - let Inst{31-27} = 0b11110; - let Inst{25-20} = 0b101010; - let Inst{15} = 0; -} - -// SUB r, sp, so_reg -def t2SUBrSPs : T2sTwoRegImm<(outs GPR:$Rd), (ins GPR:$Rn, t2_so_reg:$imm), - IIC_iALUsi, - "sub", "\t$Rd, $Rn, $imm", []> { - let Inst{31-27} = 0b11101; - let Inst{26-25} = 0b01; - let Inst{24-21} = 0b1101; - let Inst{19-16} = 0b1101; // Rn = sp - let Inst{15} = 0; -} -} // end isCodeGenOnly = 1 - //===----------------------------------------------------------------------===// // Load / store Instructions. // diff --git a/lib/Target/ARM/ARMLoadStoreOptimizer.cpp b/lib/Target/ARM/ARMLoadStoreOptimizer.cpp index c843382..c6efea1 100644 --- a/lib/Target/ARM/ARMLoadStoreOptimizer.cpp +++ b/lib/Target/ARM/ARMLoadStoreOptimizer.cpp @@ -329,13 +329,9 @@ ARMLoadStoreOpt::MergeOps(MachineBasicBlock &MBB, if (NewBase == 0) return false; } - int BaseOpc = !isThumb2 - ? ARM::ADDri - : ((Base == ARM::SP) ? ARM::t2ADDrSPi : ARM::t2ADDri); + int BaseOpc = !isThumb2 ? ARM::ADDri : ARM::t2ADDri; if (Offset < 0) { - BaseOpc = !isThumb2 - ? ARM::SUBri - : ((Base == ARM::SP) ? ARM::t2SUBrSPi : ARM::t2SUBri); + BaseOpc = !isThumb2 ? ARM::SUBri : ARM::t2SUBri; Offset = - Offset; } int ImmedOffset = isThumb2 @@ -516,8 +512,6 @@ static inline bool isMatchingDecrement(MachineInstr *MI, unsigned Base, if (!MI) return false; if (MI->getOpcode() != ARM::t2SUBri && - MI->getOpcode() != ARM::t2SUBrSPi && - MI->getOpcode() != ARM::t2SUBrSPi12 && MI->getOpcode() != ARM::tSUBspi && MI->getOpcode() != ARM::SUBri) return false; @@ -541,8 +535,6 @@ static inline bool isMatchingIncrement(MachineInstr *MI, unsigned Base, if (!MI) return false; if (MI->getOpcode() != ARM::t2ADDri && - MI->getOpcode() != ARM::t2ADDrSPi && - MI->getOpcode() != ARM::t2ADDrSPi12 && MI->getOpcode() != ARM::tADDspi && MI->getOpcode() != ARM::ADDri) return false; diff --git a/lib/Target/ARM/Thumb2InstrInfo.cpp b/lib/Target/ARM/Thumb2InstrInfo.cpp index 26e75db..0e08ea2 100644 --- a/lib/Target/ARM/Thumb2InstrInfo.cpp +++ b/lib/Target/ARM/Thumb2InstrInfo.cpp @@ -251,7 +251,7 @@ void llvm::emitT2RegPlusImmediate(MachineBasicBlock &MBB, } // sub rd, sp, so_imm - Opc = isSub ? ARM::t2SUBrSPi : ARM::t2ADDrSPi; + Opc = isSub ? ARM::t2SUBri : ARM::t2ADDri; if (ARM_AM::getT2SOImmVal(NumBytes) != -1) { NumBytes = 0; } else { @@ -425,9 +425,9 @@ bool llvm::rewriteT2FrameIndex(MachineInstr &MI, unsigned FrameRegIdx, if (Offset < 0) { Offset = -Offset; isSub = true; - MI.setDesc(TII.get(isSP ? ARM::t2SUBrSPi : ARM::t2SUBri)); + MI.setDesc(TII.get(ARM::t2SUBri)); } else { - MI.setDesc(TII.get(isSP ? ARM::t2ADDrSPi : ARM::t2ADDri)); + MI.setDesc(TII.get(ARM::t2ADDri)); } // Common case: small offset, fits into instruction. @@ -443,9 +443,7 @@ bool llvm::rewriteT2FrameIndex(MachineInstr &MI, unsigned FrameRegIdx, // Another common case: imm12. if (Offset < 4096 && (!HasCCOut || MI.getOperand(MI.getNumOperands()-1).getReg() == 0)) { - unsigned NewOpc = isSP - ? (isSub ? ARM::t2SUBrSPi12 : ARM::t2ADDrSPi12) - : (isSub ? ARM::t2SUBri12 : ARM::t2ADDri12); + unsigned NewOpc = isSub ? ARM::t2SUBri12 : ARM::t2ADDri12; MI.setDesc(TII.get(NewOpc)); MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset); diff --git a/lib/Target/ARM/Thumb2SizeReduction.cpp b/lib/Target/ARM/Thumb2SizeReduction.cpp index 9b87747..65846b2 100644 --- a/lib/Target/ARM/Thumb2SizeReduction.cpp +++ b/lib/Target/ARM/Thumb2SizeReduction.cpp @@ -57,10 +57,8 @@ namespace { static const ReduceEntry ReduceTable[] = { // Wide, Narrow1, Narrow2, imm1,imm2, lo1, lo2, P/C, PF, S { ARM::t2ADCrr, 0, ARM::tADC, 0, 0, 0, 1, 0,0, 0,0 }, - { ARM::t2ADDri, ARM::tADDi3, ARM::tADDi8, 3, 8, 1, 1, 0,0, 0,0 }, + { ARM::t2ADDri, ARM::tADDi3, ARM::tADDi8, 3, 8, 1, 1, 0,0, 0,1 }, { ARM::t2ADDrr, ARM::tADDrr, ARM::tADDhirr, 0, 0, 1, 0, 0,1, 0,0 }, - // Note: immediate scale is 4. - { ARM::t2ADDrSPi,ARM::tADDrSPi,0, 8, 0, 1, 0, 1,0, 0,1 }, { ARM::t2ADDSri,ARM::tADDi3, ARM::tADDi8, 3, 8, 1, 1, 2,2, 0,1 }, { ARM::t2ADDSrr,ARM::tADDrr, 0, 0, 0, 1, 0, 2,0, 0,1 }, { ARM::t2ANDrr, 0, ARM::tAND, 0, 0, 0, 1, 0,0, 1,0 }, @@ -291,7 +289,7 @@ static bool VerifyLowRegs(MachineInstr *MI) { Opc == ARM::t2LDMDB || Opc == ARM::t2LDMIA_UPD || Opc == ARM::t2LDMDB_UPD); bool isLROk = (Opc == ARM::t2STMIA_UPD || Opc == ARM::t2STMDB_UPD); - bool isSPOk = isPCOk || isLROk || (Opc == ARM::t2ADDrSPi); + bool isSPOk = isPCOk || isLROk; for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { const MachineOperand &MO = MI->getOperand(i); if (!MO.isReg() || MO.isImplicit()) @@ -481,6 +479,44 @@ bool Thumb2SizeReduce::ReduceSpecial(MachineBasicBlock &MBB, MachineInstr *MI, const ReduceEntry &Entry, bool LiveCPSR, MachineInstr *CPSRDef) { + unsigned Opc = MI->getOpcode(); + if (Opc == ARM::t2ADDri) { + // If the source register is SP, try to reduce to tADDrSPi, otherwise + // it's a normal reduce. + if (MI->getOperand(1).getReg() != ARM::SP) { + if (ReduceTo2Addr(MBB, MI, Entry, LiveCPSR, CPSRDef)) + return true; + return ReduceToNarrow(MBB, MI, Entry, LiveCPSR, CPSRDef); + } + // Try to reduce to tADDrSPi. + unsigned Imm = MI->getOperand(2).getImm(); + // The immediate must be in range, the destination register must be a low + // reg, and the condition flags must not be being set. + if (Imm & 3 || Imm > 1024) + return false; + if (!isARMLowRegister(MI->getOperand(0).getReg())) + return false; + const MCInstrDesc &MCID = MI->getDesc(); + if (MCID.hasOptionalDef() && + MI->getOperand(MCID.getNumOperands()-1).getReg() == ARM::CPSR) + return false; + + MachineInstrBuilder MIB = BuildMI(MBB, *MI, MI->getDebugLoc(), + TII->get(ARM::tADDrSPi)) + .addOperand(MI->getOperand(0)) + .addOperand(MI->getOperand(1)) + .addImm(Imm / 4); // The tADDrSPi has an implied scale by four. + + // Transfer MI flags. + MIB.setMIFlags(MI->getFlags()); + + DEBUG(errs() << "Converted 32-bit: " << *MI << " to 16-bit: " <<*MIB); + + MBB.erase(MI); + ++NumNarrows; + return true; + } + if (Entry.LowRegs1 && !VerifyLowRegs(MI)) return false; @@ -488,7 +524,6 @@ Thumb2SizeReduce::ReduceSpecial(MachineBasicBlock &MBB, MachineInstr *MI, if (MCID.mayLoad() || MCID.mayStore()) return ReduceLoadStore(MBB, MI, Entry); - unsigned Opc = MI->getOpcode(); switch (Opc) { default: break; case ARM::t2ADDSri: @@ -531,13 +566,6 @@ Thumb2SizeReduce::ReduceSpecial(MachineBasicBlock &MBB, MachineInstr *MI, return true; return ReduceToNarrow(MBB, MI, Entry, LiveCPSR, CPSRDef); } - case ARM::t2ADDrSPi: { - static const ReduceEntry NarrowEntry = - { ARM::t2ADDrSPi,ARM::tADDspi, 0, 7, 0, 1, 0, 1, 0, 0,1 }; - if (MI->getOperand(0).getReg() == ARM::SP) - return ReduceToNarrow(MBB, MI, NarrowEntry, LiveCPSR, CPSRDef); - return ReduceToNarrow(MBB, MI, Entry, LiveCPSR, CPSRDef); - } } return false; } @@ -645,9 +673,8 @@ Thumb2SizeReduce::ReduceToNarrow(MachineBasicBlock &MBB, MachineInstr *MI, return false; unsigned Limit = ~0U; - unsigned Scale = (Entry.WideOpc == ARM::t2ADDrSPi) ? 4 : 1; if (Entry.Imm1Limit) - Limit = ((1 << Entry.Imm1Limit) - 1) * Scale; + Limit = (1 << Entry.Imm1Limit) - 1; const MCInstrDesc &MCID = MI->getDesc(); for (unsigned i = 0, e = MCID.getNumOperands(); i != e; ++i) { @@ -658,13 +685,11 @@ Thumb2SizeReduce::ReduceToNarrow(MachineBasicBlock &MBB, MachineInstr *MI, unsigned Reg = MO.getReg(); if (!Reg || Reg == ARM::CPSR) continue; - if (Entry.WideOpc == ARM::t2ADDrSPi && Reg == ARM::SP) - continue; if (Entry.LowRegs1 && !isARMLowRegister(Reg)) return false; } else if (MO.isImm() && !MCID.OpInfo[i].isPredicate()) { - if (((unsigned)MO.getImm()) > Limit || (MO.getImm() & (Scale-1)) != 0) + if (((unsigned)MO.getImm()) > Limit) return false; } } @@ -723,15 +748,11 @@ Thumb2SizeReduce::ReduceToNarrow(MachineBasicBlock &MBB, MachineInstr *MI, if (SkipPred && isPred) continue; const MachineOperand &MO = MI->getOperand(i); - if (Scale > 1 && !isPred && MO.isImm()) - MIB.addImm(MO.getImm() / Scale); - else { - if (MO.isReg() && MO.isImplicit() && MO.getReg() == ARM::CPSR) - // Skip implicit def of CPSR. Either it's modeled as an optional - // def now or it's already an implicit def on the new instruction. - continue; - MIB.addOperand(MO); - } + if (MO.isReg() && MO.isImplicit() && MO.getReg() == ARM::CPSR) + // Skip implicit def of CPSR. Either it's modeled as an optional + // def now or it's already an implicit def on the new instruction. + continue; + MIB.addOperand(MO); } if (!MCID.isPredicable() && NewMCID.isPredicable()) AddDefaultPred(MIB); diff --git a/utils/TableGen/ARMDecoderEmitter.cpp b/utils/TableGen/ARMDecoderEmitter.cpp index a320e77..4ccab9b 100644 --- a/utils/TableGen/ARMDecoderEmitter.cpp +++ b/utils/TableGen/ARMDecoderEmitter.cpp @@ -1640,12 +1640,8 @@ ARMDEBackend::populateInstruction(const CodeGenInstruction &CGI, // Ignore tADDrSP, tADDspr, and tPICADD, prefer the generic tADDhirr. // Ignore t2SUBrSPs, prefer the t2SUB[S]r[r|s]. // Ignore t2ADDrSPs, prefer the t2ADD[S]r[r|s]. - // Ignore t2ADDrSPi/t2SUBrSPi, which have more generic couterparts. - // Ignore t2ADDrSPi12/t2SUBrSPi12, which have more generic couterparts if (Name == "tADDrSP" || Name == "tADDspr" || Name == "tPICADD" || - Name == "t2SUBrSPs" || Name == "t2ADDrSPs" || - Name == "t2ADDrSPi" || Name == "t2SUBrSPi" || - Name == "t2ADDrSPi12" || Name == "t2SUBrSPi12") + Name == "t2SUBrSPs" || Name == "t2ADDrSPs") return false; // FIXME: Use ldr.n to work around a Darwin assembler bug. -- cgit v1.1 From 9056e9032001a2d47057cecec5e39895cbc31799 Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Wed, 29 Jun 2011 23:49:12 +0000 Subject: We don't want to use relocations inside the compact unwind section. Just use the symbols instead. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134115 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/MC/MCDwarf.cpp | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp index d232d84..14a1081 100644 --- a/lib/MC/MCDwarf.cpp +++ b/lib/MC/MCDwarf.cpp @@ -637,9 +637,6 @@ bool FrameEmitterImpl::EmitCompactUnwind(MCStreamer &Streamer, const TargetAsmInfo &TAI = Context.getTargetAsmInfo(); Streamer.SwitchSection(TAI.getCompactUnwindSection()); - unsigned FDEEncoding = TAI.getFDEEncoding(UsingCFI); - unsigned Size = getSizeForEncoding(Streamer, FDEEncoding); - // range-start range-length compact-unwind-enc personality-func lsda // _foo LfooEnd-_foo 0x00000023 0 0 // _bar LbarEnd-_bar 0x00000025 __gxx_personality except_tab1 @@ -663,13 +660,31 @@ bool FrameEmitterImpl::EmitCompactUnwind(MCStreamer &Streamer, // .quad except_tab1 // Range Start - EmitSymbol(Streamer, *Frame.Begin, FDEEncoding); + unsigned FDEEncoding = TAI.getFDEEncoding(UsingCFI); + unsigned Size = getSizeForEncoding(Streamer, FDEEncoding); + Streamer.EmitSymbolValue(Frame.Function, Size); // Range Length const MCExpr *Range = MakeStartMinusEndExpr(Streamer, *Frame.Begin, *Frame.End, 0); Streamer.EmitAbsValue(Range, Size); + // Personality Function + if (Frame.Personality) { + Size = getSizeForEncoding(Streamer, Frame.PersonalityEncoding); + Streamer.EmitSymbolValue(Frame.Personality, Size); + } else { + Streamer.EmitIntValue(Frame.PersonalityEncoding, 0); // No personality fn + } + + // LSDA + if (Frame.Lsda) { + Size = getSizeForEncoding(Streamer, Frame.LsdaEncoding); + Streamer.EmitSymbolValue(Frame.Lsda, Size); + } else { + Streamer.EmitIntValue(Frame.LsdaEncoding, 0); // No LSDA + } + return true; #endif } -- cgit v1.1 From 272511f518127aae8c96935689b5607455542863 Mon Sep 17 00:00:00 2001 From: Devang Patel Date: Wed, 29 Jun 2011 23:50:13 +0000 Subject: Revert r133953 for now. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134116 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CodeGen/FastISel.h | 4 - lib/CodeGen/SelectionDAG/FastISel.cpp | 22 ----- lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 2 - test/CodeGen/X86/dbg-materialized-reg-loc.ll | 120 -------------------------- 4 files changed, 148 deletions(-) delete mode 100644 test/CodeGen/X86/dbg-materialized-reg-loc.ll diff --git a/include/llvm/CodeGen/FastISel.h b/include/llvm/CodeGen/FastISel.h index 14960a3..962a4e2 100644 --- a/include/llvm/CodeGen/FastISel.h +++ b/include/llvm/CodeGen/FastISel.h @@ -118,10 +118,6 @@ public: DebugLoc DL; }; - /// recomputeDebugLocForMaterializedRegs - Recompute debug location for - /// very first instruction in a basic block. - void recomputeDebugLocForMaterializedRegs(); - /// enterLocalValueArea - Prepare InsertPt to begin inserting instructions /// into the local value area and return the old insert position. SavePoint enterLocalValueArea(); diff --git a/lib/CodeGen/SelectionDAG/FastISel.cpp b/lib/CodeGen/SelectionDAG/FastISel.cpp index 580239a..ea7fead 100644 --- a/lib/CodeGen/SelectionDAG/FastISel.cpp +++ b/lib/CodeGen/SelectionDAG/FastISel.cpp @@ -292,28 +292,6 @@ void FastISel::recomputeInsertPt() { ++FuncInfo.InsertPt; } -/// recomputeDebugLocForMaterializedRegs - Recompute debug location for -/// very first instruction in a basic block. All instructions emitted -/// to materialize registers do not have location information, see -/// enterLocalValueArea(), becase they may not be emited at the right -/// location. -void FastISel::recomputeDebugLocForMaterializedRegs() { - if (!getLastLocalValue()) - return; - MachineInstr *First = FuncInfo.MBB->getFirstNonPHI(); - if (!First->getDebugLoc().isUnknown()) - return; - - for (MachineBasicBlock::iterator I = FuncInfo.MBB->begin(), - E = FuncInfo.MBB->end(); I != E; ++I) { - DebugLoc DL = I->getDebugLoc(); - if (!DL.isUnknown()) { - First->setDebugLoc(DL); - return; - } - } -} - FastISel::SavePoint FastISel::enterLocalValueArea() { MachineBasicBlock::iterator OldInsertPt = FuncInfo.InsertPt; DebugLoc OldDL = DL; diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 8cdc63d..87bb296 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -964,8 +964,6 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) { else ++NumFastIselBlocks; - if (FastIS) - FastIS->recomputeDebugLocForMaterializedRegs(); if (Begin != BI) { // Run SelectionDAG instruction selection on the remainder of the block // not handled by FastISel. If FastISel is not run, this is the entire diff --git a/test/CodeGen/X86/dbg-materialized-reg-loc.ll b/test/CodeGen/X86/dbg-materialized-reg-loc.ll deleted file mode 100644 index 9fa6a67..0000000 --- a/test/CodeGen/X86/dbg-materialized-reg-loc.ll +++ /dev/null @@ -1,120 +0,0 @@ -; RUN: llc -O0 < %s | FileCheck %s -; Radar 9223880 -; CHECK: .loc 1 17 64 -; CHECK: movl $0, %esi - -target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" -target triple = "x86_64-apple-macosx10.7.0" - -%class.LanguageRuntime = type opaque -%class.Process = type { i8 } - -define zeroext i1 @_Z15SetDynamicValuev() uwtable ssp { -entry: - %retval = alloca i1, align 1 - %process = alloca %class.Process*, align 8 - %cpp_runtime = alloca %class.LanguageRuntime*, align 8 - %objc_runtime = alloca %class.LanguageRuntime*, align 8 - %call = call zeroext i1 @_Z24IsPointerOrReferenceTypev(), !dbg !15 - br i1 %call, label %if.end, label %if.then, !dbg !15 - -if.then: ; preds = %entry - store i1 false, i1* %retval, !dbg !17 - br label %return, !dbg !17 - -if.end: ; preds = %entry - call void @llvm.dbg.declare(metadata !{%class.Process** %process}, metadata !18), !dbg !20 - %call1 = call %class.Process* @_Z10GetProcessv(), !dbg !21 - store %class.Process* %call1, %class.Process** %process, align 8, !dbg !21 - %tmp = load %class.Process** %process, align 8, !dbg !22 - %tobool = icmp ne %class.Process* %tmp, null, !dbg !22 - br i1 %tobool, label %if.end3, label %if.then2, !dbg !22 - -if.then2: ; preds = %if.end - store i1 false, i1* %retval, !dbg !23 - br label %return, !dbg !23 - -if.end3: ; preds = %if.end - call void @llvm.dbg.declare(metadata !{%class.LanguageRuntime** %cpp_runtime}, metadata !24), !dbg !25 - %tmp5 = load %class.Process** %process, align 8, !dbg !26 - %call6 = call %class.LanguageRuntime* @_ZN7Process18GetLanguageRuntimeEi(%class.Process* %tmp5, i32 0), !dbg !26 - store %class.LanguageRuntime* %call6, %class.LanguageRuntime** %cpp_runtime, align 8, !dbg !26 - %tmp7 = load %class.LanguageRuntime** %cpp_runtime, align 8, !dbg !27 - %tobool8 = icmp ne %class.LanguageRuntime* %tmp7, null, !dbg !27 - br i1 %tobool8, label %if.then9, label %if.end10, !dbg !27 - -if.then9: ; preds = %if.end3 - store i1 true, i1* %retval, !dbg !28 - br label %return, !dbg !28 - -if.end10: ; preds = %if.end3 - call void @llvm.dbg.declare(metadata !{%class.LanguageRuntime** %objc_runtime}, metadata !30), !dbg !31 - %tmp12 = load %class.Process** %process, align 8, !dbg !32 - %call13 = call %class.LanguageRuntime* @_ZN7Process18GetLanguageRuntimeEi(%class.Process* %tmp12, i32 1), !dbg !32 - store %class.LanguageRuntime* %call13, %class.LanguageRuntime** %objc_runtime, align 8, !dbg !32 - %tmp14 = load %class.LanguageRuntime** %objc_runtime, align 8, !dbg !33 - %tobool15 = icmp ne %class.LanguageRuntime* %tmp14, null, !dbg !33 - br i1 %tobool15, label %if.then16, label %if.end17, !dbg !33 - -if.then16: ; preds = %if.end10 - store i1 true, i1* %retval, !dbg !34 - br label %return, !dbg !34 - -if.end17: ; preds = %if.end10 - store i1 false, i1* %retval, !dbg !36 - br label %return, !dbg !36 - -return: ; preds = %if.end17, %if.then16, %if.then9, %if.then2, %if.then - %0 = load i1* %retval, !dbg !37 - ret i1 %0, !dbg !37 -} - -declare zeroext i1 @_Z24IsPointerOrReferenceTypev() - -declare void @llvm.dbg.declare(metadata, metadata) nounwind readnone - -declare %class.Process* @_Z10GetProcessv() - -declare %class.LanguageRuntime* @_ZN7Process18GetLanguageRuntimeEi(%class.Process*, i32) - -!llvm.dbg.cu = !{!0} -!llvm.dbg.sp = !{!1, !6} - -!0 = metadata !{i32 589841, i32 0, i32 4, metadata !"my_vo.cpp", metadata !"/private/tmp", metadata !"clang version 3.0 (trunk 133629)", i1 true, i1 false, metadata !"", i32 0} ; [ DW_TAG_compile_unit ] -!1 = metadata !{i32 589870, i32 0, metadata !2, metadata !"SetDynamicValue", metadata !"SetDynamicValue", metadata !"_Z15SetDynamicValuev", metadata !2, i32 9, metadata !3, i1 false, i1 true, i32 0, i32 0, i32 0, i32 256, i1 false, i1 ()* @_Z15SetDynamicValuev, null, null} ; [ DW_TAG_subprogram ] -!2 = metadata !{i32 589865, metadata !"my_vo.cpp", metadata !"/private/tmp", metadata !0} ; [ DW_TAG_file_type ] -!3 = metadata !{i32 589845, metadata !2, metadata !"", metadata !2, i32 0, i64 0, i64 0, i32 0, i32 0, i32 0, metadata !4, i32 0, i32 0} ; [ DW_TAG_subroutine_type ] -!4 = metadata !{metadata !5} -!5 = metadata !{i32 589860, metadata !0, metadata !"bool", null, i32 0, i64 8, i64 8, i64 0, i32 0, i32 2} ; [ DW_TAG_base_type ] -!6 = metadata !{i32 589870, i32 0, metadata !7, metadata !"GetLanguageRuntime", metadata !"GetLanguageRuntime", metadata !"_ZN7Process18GetLanguageRuntimeEi", metadata !2, i32 4, metadata !9, i1 false, i1 false, i32 0, i32 0, null, i32 256, i1 false, null, null} ; [ DW_TAG_subprogram ] -!7 = metadata !{i32 589826, metadata !0, metadata !"Process", metadata !2, i32 2, i64 8, i64 8, i32 0, i32 0, null, metadata !8, i32 0, null, null} ; [ DW_TAG_class_type ] -!8 = metadata !{metadata !6} -!9 = metadata !{i32 589845, metadata !2, metadata !"", metadata !2, i32 0, i64 0, i64 0, i32 0, i32 0, i32 0, metadata !10, i32 0, i32 0} ; [ DW_TAG_subroutine_type ] -!10 = metadata !{metadata !11, metadata !13, metadata !14} -!11 = metadata !{i32 589839, metadata !0, metadata !"", null, i32 0, i64 64, i64 64, i64 0, i32 0, metadata !12} ; [ DW_TAG_pointer_type ] -!12 = metadata !{i32 589843, metadata !0, metadata !"LanguageRuntime", metadata !2, i32 1, i64 0, i64 0, i32 0, i32 4, i32 0, null, i32 0, i32 0} ; [ DW_TAG_structure_type ] -!13 = metadata !{i32 589839, metadata !0, metadata !"", i32 0, i32 0, i64 64, i64 64, i64 0, i32 64, metadata !7} ; [ DW_TAG_pointer_type ] -!14 = metadata !{i32 589860, metadata !0, metadata !"int", null, i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] -!15 = metadata !{i32 10, i32 3, metadata !16, null} -!16 = metadata !{i32 589835, metadata !1, i32 9, i32 24, metadata !2, i32 0} ; [ DW_TAG_lexical_block ] -!17 = metadata !{i32 11, i32 5, metadata !16, null} -!18 = metadata !{i32 590080, metadata !16, metadata !"process", metadata !2, i32 13, metadata !19, i32 0} ; [ DW_TAG_auto_variable ] -!19 = metadata !{i32 589839, metadata !0, metadata !"", null, i32 0, i64 64, i64 64, i64 0, i32 0, metadata !7} ; [ DW_TAG_pointer_type ] -!20 = metadata !{i32 13, i32 12, metadata !16, null} -!21 = metadata !{i32 13, i32 34, metadata !16, null} -!22 = metadata !{i32 14, i32 3, metadata !16, null} -!23 = metadata !{i32 15, i32 5, metadata !16, null} -!24 = metadata !{i32 590080, metadata !16, metadata !"cpp_runtime", metadata !2, i32 17, metadata !11, i32 0} ; [ DW_TAG_auto_variable ] -!25 = metadata !{i32 17, i32 20, metadata !16, null} -!26 = metadata !{i32 17, i32 64, metadata !16, null} -!27 = metadata !{i32 18, i32 3, metadata !16, null} -!28 = metadata !{i32 19, i32 5, metadata !29, null} -!29 = metadata !{i32 589835, metadata !16, i32 18, i32 20, metadata !2, i32 1} ; [ DW_TAG_lexical_block ] -!30 = metadata !{i32 590080, metadata !16, metadata !"objc_runtime", metadata !2, i32 22, metadata !11, i32 0} ; [ DW_TAG_auto_variable ] -!31 = metadata !{i32 22, i32 20, metadata !16, null} -!32 = metadata !{i32 22, i32 65, metadata !16, null} -!33 = metadata !{i32 23, i32 3, metadata !16, null} -!34 = metadata !{i32 24, i32 5, metadata !35, null} -!35 = metadata !{i32 589835, metadata !16, i32 23, i32 21, metadata !2, i32 2} ; [ DW_TAG_lexical_block ] -!36 = metadata !{i32 26, i32 3, metadata !16, null} -!37 = metadata !{i32 27, i32 1, metadata !16, null} -- cgit v1.1 From 4498d39680abe3970dc84dca973aff46d0f9039b Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Wed, 29 Jun 2011 23:53:16 +0000 Subject: Stupid error: If the LSDA and Personality functions aren't there, emit 0 instead of the encoding. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134117 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/MC/MCDwarf.cpp | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp index 14a1081..d4a2234 100644 --- a/lib/MC/MCDwarf.cpp +++ b/lib/MC/MCDwarf.cpp @@ -670,20 +670,18 @@ bool FrameEmitterImpl::EmitCompactUnwind(MCStreamer &Streamer, Streamer.EmitAbsValue(Range, Size); // Personality Function - if (Frame.Personality) { - Size = getSizeForEncoding(Streamer, Frame.PersonalityEncoding); + Size = getSizeForEncoding(Streamer, Frame.PersonalityEncoding); + if (Frame.Personality) Streamer.EmitSymbolValue(Frame.Personality, Size); - } else { - Streamer.EmitIntValue(Frame.PersonalityEncoding, 0); // No personality fn - } + else + Streamer.EmitIntValue(0, Size); // No personality fn // LSDA - if (Frame.Lsda) { - Size = getSizeForEncoding(Streamer, Frame.LsdaEncoding); + Size = getSizeForEncoding(Streamer, Frame.LsdaEncoding); + if (Frame.Lsda) Streamer.EmitSymbolValue(Frame.Lsda, Size); - } else { - Streamer.EmitIntValue(Frame.LsdaEncoding, 0); // No LSDA - } + else + Streamer.EmitIntValue(0, Size); // No LSDA return true; #endif -- cgit v1.1 From 9287a6eef336585628a55e1f33e1e3ea9d7f81cf Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Thu, 30 Jun 2011 00:30:52 +0000 Subject: * Use the proper size to output the range size. * Rough in the compact encoding part. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134119 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/MC/MCDwarf.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp index d4a2234..fd55cc0 100644 --- a/lib/MC/MCDwarf.cpp +++ b/lib/MC/MCDwarf.cpp @@ -667,7 +667,14 @@ bool FrameEmitterImpl::EmitCompactUnwind(MCStreamer &Streamer, // Range Length const MCExpr *Range = MakeStartMinusEndExpr(Streamer, *Frame.Begin, *Frame.End, 0); - Streamer.EmitAbsValue(Range, Size); + Streamer.EmitAbsValue(Range, 4); + + // FIXME: + // Compact Encoding + uint32_t Encoding = 0; + Size = getSizeForEncoding(Streamer, dwarf::DW_EH_PE_udata4); + Streamer.EmitIntValue(Encoding, Size); + // Personality Function Size = getSizeForEncoding(Streamer, Frame.PersonalityEncoding); -- cgit v1.1 From 5d8aa345dd8f92d572a3c639ee7c6f5a7a932384 Mon Sep 17 00:00:00 2001 From: Eric Christopher Date: Thu, 30 Jun 2011 00:48:30 +0000 Subject: Fix a small thinko for constant i64 lock/orq optimization where we we didn't have an opcode for 64-bit constant or expressions. Fixes rdar://9692967 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134121 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86ISelDAGToDAG.cpp | 6 ++++-- test/CodeGen/X86/atomic-or.ll | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 test/CodeGen/X86/atomic-or.ll diff --git a/lib/Target/X86/X86ISelDAGToDAG.cpp b/lib/Target/X86/X86ISelDAGToDAG.cpp index 1fcc274..15c1917 100644 --- a/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -1612,16 +1612,18 @@ SDNode *X86DAGToDAGISel::SelectAtomicLoadArith(SDNode *Node, EVT NVT) { Opc = AtomicOpcTbl[Op][I32]; break; case MVT::i64: + Opc = AtomicOpcTbl[Op][I64]; if (isCN) { if (immSext8(Val.getNode())) Opc = AtomicOpcTbl[Op][SextConstantI64]; else if (i64immSExt32(Val.getNode())) Opc = AtomicOpcTbl[Op][ConstantI64]; - } else - Opc = AtomicOpcTbl[Op][I64]; + } break; } + assert(Opc != 0 && "Invalid arith lock transform!"); + DebugLoc dl = Node->getDebugLoc(); SDValue Undef = SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, NVT), 0); diff --git a/test/CodeGen/X86/atomic-or.ll b/test/CodeGen/X86/atomic-or.ll new file mode 100644 index 0000000..cd62290 --- /dev/null +++ b/test/CodeGen/X86/atomic-or.ll @@ -0,0 +1,18 @@ +; RUN: llc < %s -march=x86-64 | FileCheck %s + +; rdar://9692967 + +define void @do_the_sync(i64* %p, i32 %b) nounwind { +entry: + %p.addr = alloca i64*, align 8 + store i64* %p, i64** %p.addr, align 8 + %tmp = load i64** %p.addr, align 8 + call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) +; CHECK: lock +; CHECK-NEXT: orq $2147483648 + %0 = call i64 @llvm.atomic.load.or.i64.p0i64(i64* %tmp, i64 2147483648) + call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) + ret void +} +declare i64 @llvm.atomic.load.or.i64.p0i64(i64* nocapture, i64) nounwind +declare void @llvm.memory.barrier(i1, i1, i1, i1, i1) nounwind -- cgit v1.1 From 0a1509e779d3f97bb1df68c9e63c41ff5b66441d Mon Sep 17 00:00:00 2001 From: Eric Christopher Date: Thu, 30 Jun 2011 01:05:46 +0000 Subject: Make sure we use the correct register class here since we'll need to care about spill values. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134122 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Alpha/AlphaISelLowering.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/Target/Alpha/AlphaISelLowering.cpp b/lib/Target/Alpha/AlphaISelLowering.cpp index 54433a4..daf9555 100644 --- a/lib/Target/Alpha/AlphaISelLowering.cpp +++ b/lib/Target/Alpha/AlphaISelLowering.cpp @@ -835,7 +835,8 @@ getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const case 'r': return std::make_pair(0U, Alpha::GPRCRegisterClass); case 'f': - return std::make_pair(0U, Alpha::F4RCRegisterClass); + return VT == MVT::f64 ? std::make_pair(0U, Alpha::F8RCRegisterClass) : + std::make_pair(0U, Alpha::F4RCRegisterClass); } } return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT); -- cgit v1.1 From 5244c4cc2fd31e49bae2b192bd824a94b6ad5331 Mon Sep 17 00:00:00 2001 From: Eric Christopher Date: Thu, 30 Jun 2011 01:20:03 +0000 Subject: Remove getRegClassForInlineAsmConstraint and all dependencies. Fixes rdar://9643582 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134123 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Target/TargetLowering.h | 7 -- lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 101 ----------------------- lib/CodeGen/SelectionDAG/TargetLowering.cpp | 7 -- 3 files changed, 115 deletions(-) diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index c3f5f2b..f684163 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -1421,13 +1421,6 @@ public: /// is for this target. virtual ConstraintType getConstraintType(const std::string &Constraint) const; - /// getRegClassForInlineAsmConstraint - Given a constraint letter (e.g. "r"), - /// return a list of registers that can be used to satisfy the constraint. - /// This should only be used for C_RegisterClass constraints. - virtual std::vector - getRegClassForInlineAsmConstraint(const std::string &Constraint, - EVT VT) const; - /// getRegForInlineAsmConstraint - Given a physical register constraint (e.g. /// {edx}), return the register number and the register class for the /// register. diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 3001206..ea59ca1 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -5428,55 +5428,6 @@ typedef SmallVector SDISelAsmOperandInfoVector; } // end anonymous namespace -/// isAllocatableRegister - If the specified register is safe to allocate, -/// i.e. it isn't a stack pointer or some other special register, return the -/// register class for the register. Otherwise, return null. -static const TargetRegisterClass * -isAllocatableRegister(unsigned Reg, MachineFunction &MF, - const TargetLowering &TLI, - const TargetRegisterInfo *TRI) { - EVT FoundVT = MVT::Other; - const TargetRegisterClass *FoundRC = 0; - for (TargetRegisterInfo::regclass_iterator RCI = TRI->regclass_begin(), - E = TRI->regclass_end(); RCI != E; ++RCI) { - EVT ThisVT = MVT::Other; - - const TargetRegisterClass *RC = *RCI; - if (!RC->isAllocatable()) - continue; - // If none of the value types for this register class are valid, we - // can't use it. For example, 64-bit reg classes on 32-bit targets. - for (TargetRegisterClass::vt_iterator I = RC->vt_begin(), E = RC->vt_end(); - I != E; ++I) { - if (TLI.isTypeLegal(*I)) { - // If we have already found this register in a different register class, - // choose the one with the largest VT specified. For example, on - // PowerPC, we favor f64 register classes over f32. - if (FoundVT == MVT::Other || FoundVT.bitsLT(*I)) { - ThisVT = *I; - break; - } - } - } - - if (ThisVT == MVT::Other) continue; - - // NOTE: This isn't ideal. In particular, this might allocate the - // frame pointer in functions that need it (due to them not being taken - // out of allocation, because a variable sized allocation hasn't been seen - // yet). This is a slight code pessimization, but should still work. - ArrayRef RawOrder = RC->getRawAllocationOrder(MF); - if (std::find(RawOrder.begin(), RawOrder.end(), Reg) != RawOrder.end()) { - // We found a matching register class. Keep looking at others in case - // we find one with larger registers that this physreg is also in. - FoundRC = RC; - FoundVT = ThisVT; - break; - } - } - return FoundRC; -} - /// GetRegistersForValue - Assign registers (virtual or physical) for the /// specified operand. We prefer to assign virtual registers, to allow the /// register allocator to handle the assignment process. However, if the asm @@ -5611,58 +5562,6 @@ static void GetRegistersForValue(SelectionDAG &DAG, return; } - // This is a reference to a register class that doesn't directly correspond - // to an LLVM register class. Allocate NumRegs consecutive, available, - // registers from the class. - std::vector RegClassRegs - = TLI.getRegClassForInlineAsmConstraint(OpInfo.ConstraintCode, - OpInfo.ConstraintVT); - - const TargetRegisterInfo *TRI = DAG.getTarget().getRegisterInfo(); - BitVector Reserved = TRI->getReservedRegs(MF); - unsigned NumAllocated = 0; - for (unsigned i = 0, e = RegClassRegs.size(); i != e; ++i) { - unsigned Reg = RegClassRegs[i]; - // Filter out the reserved registers, but note that reserved registers are - // not fully determined at this point. We may still decide we need a frame - // pointer. - if (Reserved.test(Reg)) - continue; - // See if this register is available. - if ((isOutReg && OutputRegs.count(Reg)) || // Already used. - (isInReg && InputRegs.count(Reg))) { // Already used. - // Make sure we find consecutive registers. - NumAllocated = 0; - continue; - } - - // Check to see if this register is allocatable (i.e. don't give out the - // stack pointer). - const TargetRegisterClass *RC = isAllocatableRegister(Reg, MF, TLI, TRI); - if (!RC) { // Couldn't allocate this register. - // Reset NumAllocated to make sure we return consecutive registers. - NumAllocated = 0; - continue; - } - - // Okay, this register is good, we can use it. - ++NumAllocated; - - // If we allocated enough consecutive registers, succeed. - if (NumAllocated == NumRegs) { - unsigned RegStart = (i-NumAllocated)+1; - unsigned RegEnd = i+1; - // Mark all of the allocated registers used. - for (unsigned i = RegStart; i != RegEnd; ++i) - Regs.push_back(RegClassRegs[i]); - - OpInfo.AssignedRegs = RegsForValue(Regs, *RC->vt_begin(), - OpInfo.ConstraintVT); - OpInfo.MarkAllocatedRegs(isOutReg, isInReg, OutputRegs, InputRegs, *TRI); - return; - } - } - // Otherwise, we couldn't allocate enough registers for this. } diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp index 474dd7a..758296e 100644 --- a/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -2737,13 +2737,6 @@ void TargetLowering::LowerAsmOperandForConstraint(SDValue Op, } } -std::vector TargetLowering:: -getRegClassForInlineAsmConstraint(const std::string &Constraint, - EVT VT) const { - return std::vector(); -} - - std::pair TargetLowering:: getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const { -- cgit v1.1 From 60ac719c85366da04852c204aea5aa86d66dbb07 Mon Sep 17 00:00:00 2001 From: Andrew Trick Date: Thu, 30 Jun 2011 01:27:23 +0000 Subject: indvars -disable-iv-rewrite: handle an edge case involving identity phis. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134124 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Scalar/IndVarSimplify.cpp | 11 +++++-- test/Transforms/IndVarSimplify/no-iv-rewrite.ll | 39 ++++++++++++++++++++----- 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/lib/Transforms/Scalar/IndVarSimplify.cpp b/lib/Transforms/Scalar/IndVarSimplify.cpp index 2a3e472..00f8831 100644 --- a/lib/Transforms/Scalar/IndVarSimplify.cpp +++ b/lib/Transforms/Scalar/IndVarSimplify.cpp @@ -1015,9 +1015,9 @@ bool IndVarSimplify::EliminateIVUser(Instruction *UseInst, (SE->getSCEV(UseInst) != SE->getSCEV(IVOperand))) return false; - UseInst->replaceAllUsesWith(IVOperand); - DEBUG(dbgs() << "INDVARS: Eliminated identity: " << *UseInst << '\n'); + + UseInst->replaceAllUsesWith(IVOperand); ++NumElimIdentity; Changed = true; DeadInsts.push_back(UseInst); @@ -1037,7 +1037,9 @@ static void pushIVUsers( // Avoid infinite or exponential worklist processing. // Also ensure unique worklist users. - if (Simplified.insert(User)) + // If Def is a LoopPhi, it may not be in the Simplified set, so check for + // self edges first. + if (User != Def && Simplified.insert(User)) SimpleIVUsers.push_back(std::make_pair(User, Def)); } } @@ -1111,6 +1113,9 @@ void IndVarSimplify::SimplifyIVUsersNoRewrite(Loop *L, SCEVExpander &Rewriter) { // Use-def pairs if IVUsers waiting to be processed for CurrIV. SmallVector, 8> SimpleIVUsers; + // Push users of the current LoopPhi. In rare cases, pushIVUsers may be + // called multiple times for the same LoopPhi. This is the proper thing to + // do for loop header phis that use each other. pushIVUsers(CurrIV, Simplified, SimpleIVUsers); while (!SimpleIVUsers.empty()) { diff --git a/test/Transforms/IndVarSimplify/no-iv-rewrite.ll b/test/Transforms/IndVarSimplify/no-iv-rewrite.ll index 3395be2..0187170 100644 --- a/test/Transforms/IndVarSimplify/no-iv-rewrite.ll +++ b/test/Transforms/IndVarSimplify/no-iv-rewrite.ll @@ -23,7 +23,7 @@ ph: ; sext should be eliminated while preserving gep inboundsness. ; CHECK-NOT: sext ; CHECK: getelementptr inbounds -; CHECK: exit +; CHECK: exit: loop: %i.02 = phi i32 [ 0, %ph ], [ %iinc, %loop ] %s.01 = phi i32 [ 0, %ph ], [ %sinc, %loop ] @@ -64,7 +64,7 @@ ph: ; CHECK: getelementptr inbounds ; %vall sext should obviously not be eliminated ; CHECK: sext -; CHECK: exit +; CHECK: exit: loop: %i.02 = phi i32 [ 0, %ph ], [ %iinc, %loop ] %s.01 = phi i64 [ 0, %ph ], [ %sinc, %loop ] @@ -108,7 +108,7 @@ ph: ; Preserve gep inboundsness, and don't factor it. ; CHECK: getelementptr inbounds i32* %ptriv, i32 1 ; CHECK-NOT: add -; CHECK: exit +; CHECK: exit: loop: %ptriv = phi i32* [ %first, %ph ], [ %ptrpost, %loop ] %ofs = sext i32 %idx to i64 @@ -139,7 +139,7 @@ entry: ; CHECK: phi i32 ; CHECK: bitcast ; CHECK: getelementptr -; CHECK: exit +; CHECK: exit: loop: %iv = phi i32 [%start, %entry], [%next, %loop] %p = phi %struct* [%base, %entry], [%pinc, %loop] @@ -157,12 +157,13 @@ exit: } define void @maxvisitor(i32 %limit, i32* %base) nounwind { -entry: br label %loop +entry: + br label %loop ; CHECK: loop: ; CHECK: phi i64 ; CHECK: trunc -; CHECK: exit +; CHECK: exit: loop: %idx = phi i32 [ 0, %entry ], [ %idx.next, %loop.inc ] %max = phi i32 [ 0, %entry ], [ %max.next, %loop.inc ] @@ -186,4 +187,28 @@ loop.inc: exit: ret void -} \ No newline at end of file +} + +; CHECK: loop: +; CHECK: phi i32 +; CHECK-NOT: phi +; CHECK: exit: +define void @identityphi(i32 %limit) nounwind { +entry: + br label %loop + +loop: + %iv = phi i32 [ 0, %entry], [ %iv.next, %control ] + br i1 undef, label %if.then, label %control + +if.then: + br label %control + +control: + %iv.next = phi i32 [ %iv, %loop ], [ undef, %if.then ] + %cmp = icmp slt i32 %iv.next, %limit + br i1 %cmp, label %loop, label %exit + +exit: + ret void +} -- cgit v1.1 From 87360f73ae205854f100ba5fb7eef7b90ac3bc27 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Thu, 30 Jun 2011 01:30:39 +0000 Subject: Reapply r134047 now that the world is ready for it. This patch will sometimes choose live range split points next to interference instead of always splitting next to a register point. That means spill code can now appear almost anywhere, and it was necessary to fix code that didn't expect that. The difficult places were: - Between a CALL returning a value on the x87 stack and the corresponding FpPOP_RETVAL (was FpGET_ST0). Probably also near x87 inline assembly, but that didn't actually show up in testing. - Between a CALL popping arguments off the stack and the corresponding ADJCALLSTACKUP. Both are fixed now. The only place spill code can't appear is after terminators, see SplitAnalysis::getLastSplitPoint. Original commit message: Rewrite RAGreedy::splitAroundRegion, now with cool ASCII art. This function has to deal with a lot of special cases, and the old version got it wrong sometimes. In particular, it would sometimes leave multiple uses in the stack interval in a single block. That causes bad code with multiple reloads in the same basic block. The new version handles block entry and exit in a single pass. It first eliminates all the easy cases, and then goes on to create a local interval for the blocks with difficult interference. Previously, we would only create the local interval for completely isolated blocks. It can happen that the stack interval becomes completely empty because we could allocate a register in all edge bundles, and the new local intervals deal with the interference. The empty stack interval is harmless, but we need to remove a SplitKit assertion that checks for empty intervals. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134125 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/RegAllocGreedy.cpp | 394 +++++++++++++++++++++++++++-------------- lib/CodeGen/SplitKit.cpp | 25 ++- lib/CodeGen/SplitKit.h | 10 ++ 3 files changed, 291 insertions(+), 138 deletions(-) diff --git a/lib/CodeGen/RegAllocGreedy.cpp b/lib/CodeGen/RegAllocGreedy.cpp index d0e6a64..912d899 100644 --- a/lib/CodeGen/RegAllocGreedy.cpp +++ b/lib/CodeGen/RegAllocGreedy.cpp @@ -763,32 +763,46 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg, // Create the main cross-block interval. const unsigned MainIntv = SE->openIntv(); - // First add all defs that are live out of a block. + // First handle all the blocks with uses. ArrayRef UseBlocks = SA->getUseBlocks(); for (unsigned i = 0; i != UseBlocks.size(); ++i) { const SplitAnalysis::BlockInfo &BI = UseBlocks[i]; - bool RegIn = LiveBundles[Bundles->getBundle(BI.MBB->getNumber(), 0)]; - bool RegOut = LiveBundles[Bundles->getBundle(BI.MBB->getNumber(), 1)]; + bool RegIn = BI.LiveIn && + LiveBundles[Bundles->getBundle(BI.MBB->getNumber(), 0)]; + bool RegOut = BI.LiveOut && + LiveBundles[Bundles->getBundle(BI.MBB->getNumber(), 1)]; // Create separate intervals for isolated blocks with multiple uses. - if (!RegIn && !RegOut && BI.FirstUse != BI.LastUse) { + // + // |---o---o---| Enter and leave on the stack. + // ____-----____ Create local interval for uses. + // + // | o---o---| Defined in block, leave on stack. + // -----____ Create local interval for uses. + // + // |---o---x | Enter on stack, killed in block. + // ____----- Create local interval for uses. + // + if (!RegIn && !RegOut) { DEBUG(dbgs() << "BB#" << BI.MBB->getNumber() << " isolated.\n"); - SE->splitSingleBlock(BI); - SE->selectIntv(MainIntv); + if (!BI.isOneInstr()) { + SE->splitSingleBlock(BI); + SE->selectIntv(MainIntv); + } continue; } - // Should the register be live out? - if (!BI.LiveOut || !RegOut) - continue; - SlotIndex Start, Stop; tie(Start, Stop) = Indexes->getMBBRange(BI.MBB); Intf.moveToBlock(BI.MBB->getNumber()); - DEBUG(dbgs() << "BB#" << BI.MBB->getNumber() << " -> EB#" - << Bundles->getBundle(BI.MBB->getNumber(), 1) + DEBUG(dbgs() << "EB#" << Bundles->getBundle(BI.MBB->getNumber(), 0) + << (RegIn ? " => " : " -- ") + << "BB#" << BI.MBB->getNumber() + << (RegOut ? " => " : " -- ") + << " EB#" << Bundles->getBundle(BI.MBB->getNumber(), 1) << " [" << Start << ';' << SA->getLastSplitPoint(BI.MBB->getNumber()) << '-' << Stop + << ") uses [" << BI.FirstUse << ';' << BI.LastUse << ") intf [" << Intf.first() << ';' << Intf.last() << ')'); // The interference interval should either be invalid or overlap MBB. @@ -797,150 +811,266 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg, assert((!Intf.hasInterference() || Intf.last() > Start) && "Bad interference"); - // Check interference leaving the block. + // We are now ready to decide where to split in the current block. There + // are many variables guiding the decision: + // + // - RegIn / RegOut: The global splitting algorithm's decisions for our + // ingoing and outgoing bundles. + // + // - BI.BlockIn / BI.BlockOut: Is the live range live-in and/or live-out + // from this block. + // + // - Intf.hasInterference(): Is there interference in this block. + // + // - Intf.first() / Inft.last(): The range of interference. + // + // The live range should be split such that MainIntv is live-in when RegIn + // is set, and live-out when RegOut is set. MainIntv should never overlap + // the interference, and the stack interval should never have more than one + // use per block. + + // No splits can be inserted after LastSplitPoint, overlap instead. + SlotIndex LastSplitPoint = Stop; + if (BI.LiveOut) + LastSplitPoint = SA->getLastSplitPoint(BI.MBB->getNumber()); + + // At this point, we know that either RegIn or RegOut is set. We dealt with + // the all-stack case above. + + // Blocks without interference are relatively easy. if (!Intf.hasInterference()) { - // Block is interference-free. - DEBUG(dbgs() << ", no interference"); - if (!BI.LiveThrough) { - DEBUG(dbgs() << ", not live-through.\n"); - SE->useIntv(SE->enterIntvBefore(BI.FirstUse), Stop); - continue; - } - if (!RegIn) { - // Block is live-through, but entry bundle is on the stack. - // Reload just before the first use. - DEBUG(dbgs() << ", not live-in, enter before first use.\n"); - SE->useIntv(SE->enterIntvBefore(BI.FirstUse), Stop); - continue; + DEBUG(dbgs() << ", no interference.\n"); + SE->selectIntv(MainIntv); + // The easiest case has MainIntv live through. + // + // |---o---o---| Live-in, live-out. + // ============= Use MainIntv everywhere. + // + SlotIndex From = Start, To = Stop; + + // Block entry. Reload before the first use if MainIntv is not live-in. + // + // |---o-- Enter on stack. + // ____=== Reload before first use. + // + // | o-- Defined in block. + // === Use MainIntv from def. + // + if (!RegIn) + From = SE->enterIntvBefore(BI.FirstUse); + + // Block exit. Handle cases where MainIntv is not live-out. + if (!BI.LiveOut) + // + // --x | Killed in block. + // === Use MainIntv up to kill. + // + To = SE->leaveIntvAfter(BI.LastUse); + else if (!RegOut) { + // + // --o---| Live-out on stack. + // ===____ Use MainIntv up to last use, switch to stack. + // + // -----o| Live-out on stack, last use after last split point. + // ====== Extend MainIntv to last use, overlapping. + // \____ Copy to stack interval before last split point. + // + if (BI.LastUse < LastSplitPoint) + To = SE->leaveIntvAfter(BI.LastUse); + else { + // The last use is after the last split point, it is probably an + // indirect branch. + To = SE->leaveIntvBefore(LastSplitPoint); + // Run a double interval from the split to the last use. This makes + // it possible to spill the complement without affecting the indirect + // branch. + SE->overlapIntv(To, BI.LastUse); + } } - DEBUG(dbgs() << ", live-through.\n"); - continue; - } - - // Block has interference. - DEBUG(dbgs() << ", interference to " << Intf.last()); - if (!BI.LiveThrough && Intf.last() <= BI.FirstUse) { - // The interference doesn't reach the outgoing segment. - DEBUG(dbgs() << " doesn't affect def from " << BI.FirstUse << '\n'); - SE->useIntv(BI.FirstUse, Stop); + // Paint in MainIntv liveness for this block. + SE->useIntv(From, To); continue; } - SlotIndex LastSplitPoint = SA->getLastSplitPoint(BI.MBB->getNumber()); - if (Intf.last().getBoundaryIndex() < BI.LastUse) { - // There are interference-free uses at the end of the block. - // Find the first use that can get the live-out register. - SmallVectorImpl::const_iterator UI = - std::lower_bound(SA->UseSlots.begin(), SA->UseSlots.end(), - Intf.last().getBoundaryIndex()); - assert(UI != SA->UseSlots.end() && "Couldn't find last use"); - SlotIndex Use = *UI; - assert(Use <= BI.LastUse && "Couldn't find last use"); - // Only attempt a split befroe the last split point. - if (Use.getBaseIndex() <= LastSplitPoint) { - DEBUG(dbgs() << ", free use at " << Use << ".\n"); - SlotIndex SegStart = SE->enterIntvBefore(Use); - assert(SegStart >= Intf.last() && "Couldn't avoid interference"); - assert(SegStart < LastSplitPoint && "Impossible split point"); - SE->useIntv(SegStart, Stop); - continue; - } - } + // We are now looking at a block with interference, and we know that either + // RegIn or RegOut is set. + assert(Intf.hasInterference() && (RegIn || RegOut) && "Bad invariant"); - // Interference is after the last use. - DEBUG(dbgs() << " after last use.\n"); - SlotIndex SegStart = SE->enterIntvAtEnd(*BI.MBB); - assert(SegStart >= Intf.last() && "Couldn't avoid interference"); - } + // If the live range is not live through the block, it is possible that the + // interference doesn't even overlap. Deal with those cases first. Since + // no copy instructions are required, we can tolerate interference starting + // or ending at the same instruction that kills or defines our live range. - // Now all defs leading to live bundles are handled, do everything else. - for (unsigned i = 0; i != UseBlocks.size(); ++i) { - const SplitAnalysis::BlockInfo &BI = UseBlocks[i]; - bool RegIn = LiveBundles[Bundles->getBundle(BI.MBB->getNumber(), 0)]; - bool RegOut = LiveBundles[Bundles->getBundle(BI.MBB->getNumber(), 1)]; + // Live-in, killed before interference. + // + // ~~~ Interference after kill. + // |---o---x | Killed in block. + // ========= Use MainIntv everywhere. + // + if (RegIn && !BI.LiveOut && BI.LastUse <= Intf.first()) { + DEBUG(dbgs() << ", live-in, killed before interference.\n"); + SE->selectIntv(MainIntv); + SlotIndex To = SE->leaveIntvAfter(BI.LastUse); + SE->useIntv(Start, To); + continue; + } - // Is the register live-in? - if (!BI.LiveIn || !RegIn) + // Live-out, defined after interference. + // + // ~~~ Interference before def. + // | o---o---| Defined in block. + // ========= Use MainIntv everywhere. + // + if (RegOut && !BI.LiveIn && BI.FirstUse >= Intf.last()) { + DEBUG(dbgs() << ", live-out, defined after interference.\n"); + SE->selectIntv(MainIntv); + SlotIndex From = SE->enterIntvBefore(BI.FirstUse); + SE->useIntv(From, Stop); continue; + } - // We have an incoming register. Check for interference. - SlotIndex Start, Stop; - tie(Start, Stop) = Indexes->getMBBRange(BI.MBB); - Intf.moveToBlock(BI.MBB->getNumber()); - DEBUG(dbgs() << "EB#" << Bundles->getBundle(BI.MBB->getNumber(), 0) - << " -> BB#" << BI.MBB->getNumber() << " [" << Start << ';' - << SA->getLastSplitPoint(BI.MBB->getNumber()) << '-' << Stop - << ')'); + // The interference is now known to overlap the live range, but it may + // still be easy to avoid if all the interference is on one side of the + // uses, and we enter or leave on the stack. - // Check interference entering the block. - if (!Intf.hasInterference()) { - // Block is interference-free. - DEBUG(dbgs() << ", no interference"); - if (!BI.LiveThrough) { - DEBUG(dbgs() << ", killed in block.\n"); - SE->useIntv(Start, SE->leaveIntvAfter(BI.LastUse)); - continue; - } - if (!RegOut) { - SlotIndex LastSplitPoint = SA->getLastSplitPoint(BI.MBB->getNumber()); - // Block is live-through, but exit bundle is on the stack. - // Spill immediately after the last use. - if (BI.LastUse < LastSplitPoint) { - DEBUG(dbgs() << ", uses, stack-out.\n"); - SE->useIntv(Start, SE->leaveIntvAfter(BI.LastUse)); - continue; - } - // The last use is after the last split point, it is probably an - // indirect jump. - DEBUG(dbgs() << ", uses at " << BI.LastUse << " after split point " - << LastSplitPoint << ", stack-out.\n"); - SlotIndex SegEnd = SE->leaveIntvBefore(LastSplitPoint); - SE->useIntv(Start, SegEnd); - // Run a double interval from the split to the last use. - // This makes it possible to spill the complement without affecting the - // indirect branch. - SE->overlapIntv(SegEnd, BI.LastUse); - continue; + // Live-out on stack, interference after last use. + // + // ~~~ Interference after last use. + // |---o---o---| Live-out on stack. + // =========____ Leave MainIntv after last use. + // + // ~ Interference after last use. + // |---o---o--o| Live-out on stack, late last use. + // =========____ Copy to stack after LSP, overlap MainIntv. + // + if (!RegOut && Intf.first() > BI.LastUse.getBoundaryIndex()) { + assert(RegIn && "Stack-in, stack-out should already be handled"); + if (BI.LastUse < LastSplitPoint) { + DEBUG(dbgs() << ", live-in, stack-out, interference after last use.\n"); + SE->selectIntv(MainIntv); + SlotIndex To = SE->leaveIntvAfter(BI.LastUse); + assert(To <= Intf.first() && "Expected to avoid interference"); + SE->useIntv(Start, To); + } else { + DEBUG(dbgs() << ", live-in, stack-out, avoid last split point\n"); + SE->selectIntv(MainIntv); + SlotIndex To = SE->leaveIntvBefore(LastSplitPoint); + assert(To <= Intf.first() && "Expected to avoid interference"); + SE->overlapIntv(To, BI.LastUse); + SE->useIntv(Start, To); } - // Register is live-through. - DEBUG(dbgs() << ", uses, live-through.\n"); - SE->useIntv(Start, Stop); continue; } - // Block has interference. - DEBUG(dbgs() << ", interference from " << Intf.first()); - - if (!BI.LiveThrough && Intf.first() >= BI.LastUse) { - // The interference doesn't reach the outgoing segment. - DEBUG(dbgs() << " doesn't affect kill at " << BI.LastUse << '\n'); - SE->useIntv(Start, BI.LastUse); + // Live-in on stack, interference before first use. + // + // ~~~ Interference before first use. + // |---o---o---| Live-in on stack. + // ____========= Enter MainIntv before first use. + // + if (!RegIn && Intf.last() < BI.FirstUse.getBaseIndex()) { + assert(RegOut && "Stack-in, stack-out should already be handled"); + DEBUG(dbgs() << ", stack-in, interference before first use.\n"); + SE->selectIntv(MainIntv); + SlotIndex From = SE->enterIntvBefore(BI.FirstUse); + assert(From >= Intf.last() && "Expected to avoid interference"); + SE->useIntv(From, Stop); continue; } - if (Intf.first().getBaseIndex() > BI.FirstUse) { - // There are interference-free uses at the beginning of the block. - // Find the last use that can get the register. - SmallVectorImpl::const_iterator UI = - std::lower_bound(SA->UseSlots.begin(), SA->UseSlots.end(), - Intf.first().getBaseIndex()); - assert(UI != SA->UseSlots.begin() && "Couldn't find first use"); - SlotIndex Use = (--UI)->getBoundaryIndex(); - DEBUG(dbgs() << ", free use at " << *UI << ".\n"); - SlotIndex SegEnd = SE->leaveIntvAfter(Use); - assert(SegEnd <= Intf.first() && "Couldn't avoid interference"); - SE->useIntv(Start, SegEnd); - continue; + // The interference is overlapping somewhere we wanted to use MainIntv. That + // means we need to create a local interval that can be allocated a + // different register. + DEBUG(dbgs() << ", creating local interval.\n"); + unsigned LocalIntv = SE->openIntv(); + + // We may be creating copies directly between MainIntv and LocalIntv, + // bypassing the stack interval. When we do that, we should never use the + // leaveIntv* methods as they define values in the stack interval. By + // starting from the end of the block and working our way backwards, we can + // get by with only enterIntv* methods. + // + // When selecting split points, we generally try to maximize the stack + // interval as long at it contains no uses, maximize the main interval as + // long as it doesn't overlap interference, and minimize the local interval + // that we don't know how to allocate yet. + + // Handle the block exit, set Pos to the first handled slot. + SlotIndex Pos = BI.LastUse; + if (RegOut) { + assert(Intf.last() < LastSplitPoint && "Cannot be live-out in register"); + // Create a snippet of MainIntv that is live-out. + // + // ~~~ Interference overlapping uses. + // --o---| Live-out in MainIntv. + // ----=== Switch from LocalIntv to MainIntv after interference. + // + SE->selectIntv(MainIntv); + Pos = SE->enterIntvAfter(Intf.last()); + assert(Pos >= Intf.last() && "Expected to avoid interference"); + SE->useIntv(Pos, Stop); + SE->selectIntv(LocalIntv); + } else if (BI.LiveOut) { + if (BI.LastUse < LastSplitPoint) { + // Live-out on the stack. + // + // ~~~ Interference overlapping uses. + // --o---| Live-out on stack. + // ---____ Switch from LocalIntv to stack after last use. + // + Pos = SE->leaveIntvAfter(BI.LastUse); + } else { + // Live-out on the stack, last use after last split point. + // + // ~~~ Interference overlapping uses. + // --o--o| Live-out on stack, late use. + // ------ Copy to stack before LSP, overlap LocalIntv. + // \__ + // + Pos = SE->leaveIntvBefore(LastSplitPoint); + // We need to overlap LocalIntv so it can reach LastUse. + SE->overlapIntv(Pos, BI.LastUse); + } } - // Interference is before the first use. - DEBUG(dbgs() << " before first use.\n"); - SlotIndex SegEnd = SE->leaveIntvAtTop(*BI.MBB); - assert(SegEnd <= Intf.first() && "Couldn't avoid interference"); + // When not live-out, leave Pos at LastUse. We have handled everything from + // Pos to Stop. Find the starting point for LocalIntv. + assert(SE->currentIntv() == LocalIntv && "Expecting local interval"); + + if (RegIn) { + assert(Start < Intf.first() && "Cannot be live-in with interference"); + // Live-in in MainIntv, only use LocalIntv for interference. + // + // ~~~ Interference overlapping uses. + // |---o-- Live-in in MainIntv. + // ====--- Switch to LocalIntv before interference. + // + SlotIndex Switch = SE->enterIntvBefore(Intf.first()); + assert(Switch <= Intf.first() && "Expected to avoid interference"); + SE->useIntv(Switch, Pos); + SE->selectIntv(MainIntv); + SE->useIntv(Start, Switch); + } else { + // Live-in on stack, enter LocalIntv before first use. + // + // ~~~ Interference overlapping uses. + // |---o-- Live-in in MainIntv. + // ____--- Reload to LocalIntv before interference. + // + // Defined in block. + // + // ~~~ Interference overlapping uses. + // | o-- Defined in block. + // --- Begin LocalIntv at first use. + // + SlotIndex Switch = SE->enterIntvBefore(BI.FirstUse); + SE->useIntv(Switch, Pos); + } } // Handle live-through blocks. + SE->selectIntv(MainIntv); for (unsigned i = 0, e = Cand.ActiveBlocks.size(); i != e; ++i) { unsigned Number = Cand.ActiveBlocks[i]; bool RegIn = LiveBundles[Bundles->getBundle(Number, 0)]; diff --git a/lib/CodeGen/SplitKit.cpp b/lib/CodeGen/SplitKit.cpp index 55b1114..a0952a0 100644 --- a/lib/CodeGen/SplitKit.cpp +++ b/lib/CodeGen/SplitKit.cpp @@ -636,6 +636,7 @@ unsigned SplitEditor::openIntv() { void SplitEditor::selectIntv(unsigned Idx) { assert(Idx != 0 && "Cannot select the complement interval"); assert(Idx < Edit->size() && "Can only select previously opened interval"); + DEBUG(dbgs() << " selectIntv " << OpenIdx << " -> " << Idx << '\n'); OpenIdx = Idx; } @@ -656,6 +657,24 @@ SlotIndex SplitEditor::enterIntvBefore(SlotIndex Idx) { return VNI->def; } +SlotIndex SplitEditor::enterIntvAfter(SlotIndex Idx) { + assert(OpenIdx && "openIntv not called before enterIntvAfter"); + DEBUG(dbgs() << " enterIntvAfter " << Idx); + Idx = Idx.getBoundaryIndex(); + VNInfo *ParentVNI = Edit->getParent().getVNInfoAt(Idx); + if (!ParentVNI) { + DEBUG(dbgs() << ": not live\n"); + return Idx; + } + DEBUG(dbgs() << ": valno " << ParentVNI->id << '\n'); + MachineInstr *MI = LIS.getInstructionFromIndex(Idx); + assert(MI && "enterIntvAfter called with invalid index"); + + VNInfo *VNI = defFromParent(OpenIdx, ParentVNI, Idx, *MI->getParent(), + llvm::next(MachineBasicBlock::iterator(MI))); + return VNI->def; +} + SlotIndex SplitEditor::enterIntvAtEnd(MachineBasicBlock &MBB) { assert(OpenIdx && "openIntv not called before enterIntvAtEnd"); SlotIndex End = LIS.getMBBEndIdx(&MBB); @@ -1007,12 +1026,6 @@ void SplitEditor::finish(SmallVectorImpl *LRMap) { markComplexMapped(i, ParentVNI); } -#ifndef NDEBUG - // Every new interval must have a def by now, otherwise the split is bogus. - for (LiveRangeEdit::iterator I = Edit->begin(), E = Edit->end(); I != E; ++I) - assert((*I)->hasAtLeastOneValue() && "Split interval has no value"); -#endif - // Transfer the simply mapped values, check if any are skipped. bool Skipped = transferValues(); if (Skipped) diff --git a/lib/CodeGen/SplitKit.h b/lib/CodeGen/SplitKit.h index 7174c0b..a9ccf40b 100644 --- a/lib/CodeGen/SplitKit.h +++ b/lib/CodeGen/SplitKit.h @@ -81,6 +81,12 @@ public: bool LiveThrough; ///< Live in whole block (Templ 5. above). bool LiveIn; ///< Current reg is live in. bool LiveOut; ///< Current reg is live out. + + /// isOneInstr - Returns true when this BlockInfo describes a single + /// instruction. + bool isOneInstr() const { + return SlotIndex::isSameInstr(FirstUse, LastUse); + } }; private: @@ -360,6 +366,10 @@ public: /// Return the beginning of the new live range. SlotIndex enterIntvBefore(SlotIndex Idx); + /// enterIntvAfter - Enter the open interval after the instruction at Idx. + /// Return the beginning of the new live range. + SlotIndex enterIntvAfter(SlotIndex Idx); + /// enterIntvAtEnd - Enter the open interval at the end of MBB. /// Use the open interval from he inserted copy to the MBB end. /// Return the beginning of the new live range. -- cgit v1.1 From ca0ede7655cbe126441dd13599eafdf442eff3a9 Mon Sep 17 00:00:00 2001 From: Joerg Sonnenberger Date: Thu, 30 Jun 2011 01:38:03 +0000 Subject: Recognize the xstorerng alias for VIA PadLock's xstore instruction. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134126 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86InstrSystem.td | 2 ++ test/MC/X86/padlock.s | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/lib/Target/X86/X86InstrSystem.td b/lib/Target/X86/X86InstrSystem.td index f73cff3..31de878 100644 --- a/lib/Target/X86/X86InstrSystem.td +++ b/lib/Target/X86/X86InstrSystem.td @@ -411,6 +411,8 @@ let Uses = [RDX, RAX, RCX] in let Defs = [RAX, RDI], Uses = [RDX, RDI] in def XSTORE : I<0xc0, RawFrm, (outs), (ins), "xstore", []>, A7; +def : InstAlias<"xstorerng", (XSTORE)>; + let Defs = [RSI, RDI], Uses = [RBX, RDX, RSI, RDI] in { def XCRYPTECB : I<0xc8, RawFrm, (outs), (ins), "xcryptecb", []>, A7; def XCRYPTCBC : I<0xd0, RawFrm, (outs), (ins), "xcryptcbc", []>, A7; diff --git a/test/MC/X86/padlock.s b/test/MC/X86/padlock.s index 874786f..5c523e7 100644 --- a/test/MC/X86/padlock.s +++ b/test/MC/X86/padlock.s @@ -4,6 +4,10 @@ // CHECK: xstore // CHECK: encoding: [0x0f,0xa7,0xc0] + xstorerng +// CHECK: xstore +// CHECK: encoding: [0x0f,0xa7,0xc0] + rep xcryptecb // CHECK: rep // CHECK: encoding: [0xf3] -- cgit v1.1 From 276365dd4bc0c2160f91fd8062ae1fc90c86c324 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Thu, 30 Jun 2011 01:53:36 +0000 Subject: Fix the ridiculous SubtargetFeatures API where it implicitly expects CPU name to be the first encoded as the first feature. It then uses the CPU name to look up features / scheduling itineray even though clients know full well the CPU name being used to query these properties. The fix is to just have the clients explictly pass the CPU name! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134127 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/MC/SubtargetFeature.h | 28 +++++------- include/llvm/Target/TargetRegistry.h | 7 ++- lib/ExecutionEngine/TargetSelect.cpp | 5 +-- lib/MC/MCDisassembler/Disassembler.cpp | 4 +- lib/MC/MCDisassembler/EDDisassembler.cpp | 4 +- lib/MC/SubtargetFeature.cpp | 62 +++++++++----------------- lib/Target/ARM/ARMSubtarget.cpp | 26 ++++++----- lib/Target/ARM/ARMSubtarget.h | 6 +-- lib/Target/ARM/ARMTargetMachine.cpp | 9 ++-- lib/Target/ARM/ARMTargetMachine.h | 7 +-- lib/Target/ARM/AsmParser/ARMAsmLexer.cpp | 6 ++- lib/Target/Alpha/AlphaSubtarget.cpp | 9 ++-- lib/Target/Alpha/AlphaSubtarget.h | 6 +-- lib/Target/Alpha/AlphaTargetMachine.cpp | 3 +- lib/Target/Alpha/AlphaTargetMachine.h | 2 +- lib/Target/Blackfin/BlackfinSubtarget.cpp | 7 ++- lib/Target/Blackfin/BlackfinSubtarget.h | 5 ++- lib/Target/Blackfin/BlackfinTargetMachine.cpp | 3 +- lib/Target/Blackfin/BlackfinTargetMachine.h | 2 +- lib/Target/CBackend/CTargetMachine.h | 3 +- lib/Target/CellSPU/SPUSubtarget.cpp | 3 +- lib/Target/CellSPU/SPUSubtarget.h | 6 +-- lib/Target/CellSPU/SPUTargetMachine.cpp | 4 +- lib/Target/CellSPU/SPUTargetMachine.h | 2 +- lib/Target/CppBackend/CPPTargetMachine.h | 2 +- lib/Target/MBlaze/AsmParser/MBlazeAsmLexer.cpp | 3 +- lib/Target/MBlaze/MBlazeSubtarget.cpp | 14 +++--- lib/Target/MBlaze/MBlazeSubtarget.h | 6 +-- lib/Target/MBlaze/MBlazeTargetMachine.cpp | 4 +- lib/Target/MBlaze/MBlazeTargetMachine.h | 2 +- lib/Target/MSP430/MSP430Subtarget.cpp | 4 +- lib/Target/MSP430/MSP430Subtarget.h | 6 +-- lib/Target/MSP430/MSP430TargetMachine.cpp | 3 +- lib/Target/MSP430/MSP430TargetMachine.h | 2 +- lib/Target/Mips/MipsSubtarget.cpp | 10 +++-- lib/Target/Mips/MipsSubtarget.h | 6 +-- lib/Target/Mips/MipsTargetMachine.cpp | 9 ++-- lib/Target/Mips/MipsTargetMachine.h | 5 ++- lib/Target/PTX/PTXSubtarget.cpp | 8 ++-- lib/Target/PTX/PTXSubtarget.h | 7 +-- lib/Target/PTX/PTXTargetMachine.cpp | 9 ++-- lib/Target/PTX/PTXTargetMachine.h | 7 +-- lib/Target/PowerPC/PPCSubtarget.cpp | 13 +++--- lib/Target/PowerPC/PPCSubtarget.h | 6 +-- lib/Target/PowerPC/PPCTargetMachine.cpp | 9 ++-- lib/Target/PowerPC/PPCTargetMachine.h | 7 +-- lib/Target/Sparc/SparcSubtarget.cpp | 17 ++++--- lib/Target/Sparc/SparcSubtarget.h | 6 +-- lib/Target/Sparc/SparcTargetMachine.cpp | 9 ++-- lib/Target/Sparc/SparcTargetMachine.h | 7 +-- lib/Target/SystemZ/SystemZSubtarget.cpp | 7 ++- lib/Target/SystemZ/SystemZSubtarget.h | 6 +-- lib/Target/SystemZ/SystemZTargetMachine.cpp | 3 +- lib/Target/SystemZ/SystemZTargetMachine.h | 2 +- lib/Target/X86/X86Subtarget.cpp | 11 +++-- lib/Target/X86/X86Subtarget.h | 6 +-- lib/Target/X86/X86TargetMachine.cpp | 9 ++-- lib/Target/X86/X86TargetMachine.h | 7 +-- lib/Target/XCore/XCoreSubtarget.cpp | 3 +- lib/Target/XCore/XCoreSubtarget.h | 6 +-- lib/Target/XCore/XCoreTargetMachine.cpp | 3 +- lib/Target/XCore/XCoreTargetMachine.h | 2 +- tools/llc/llc.cpp | 6 +-- tools/llvm-mc/llvm-mc.cpp | 12 +---- tools/llvm-objdump/llvm-objdump.cpp | 3 +- tools/lto/LTOCodeGenerator.cpp | 4 +- tools/lto/LTOModule.cpp | 5 ++- utils/TableGen/SubtargetEmitter.cpp | 12 ++--- 68 files changed, 271 insertions(+), 236 deletions(-) diff --git a/include/llvm/MC/SubtargetFeature.h b/include/llvm/MC/SubtargetFeature.h index cc56576..b2d7fb5 100644 --- a/include/llvm/MC/SubtargetFeature.h +++ b/include/llvm/MC/SubtargetFeature.h @@ -80,26 +80,19 @@ public: std::string getString() const; void setString(const std::string &Initial); - /// Set the CPU string. Replaces previous setting. Setting to "" clears CPU. - void setCPU(const std::string &String); - - /// Setting CPU string only if no string is set. - void setCPUIfNone(const std::string &String); - - /// Returns current CPU string. - const std::string & getCPU() const; - /// Adding Features. void AddFeature(const std::string &String, bool IsEnabled = true); - /// Get feature bits. - uint64_t getBits(const SubtargetFeatureKV *CPUTable, - size_t CPUTableSize, - const SubtargetFeatureKV *FeatureTable, - size_t FeatureTableSize); + /// Get feature bits of a CPU. + uint64_t getFeatureBits(const std::string &CPU, + const SubtargetFeatureKV *CPUTable, + size_t CPUTableSize, + const SubtargetFeatureKV *FeatureTable, + size_t FeatureTableSize); - /// Get info pointer - void *getInfo(const SubtargetInfoKV *Table, size_t TableSize); + /// Get scheduling itinerary of a CPU. + void *getItinerary(const std::string &CPU, + const SubtargetInfoKV *Table, size_t TableSize); /// Print feature string. void print(raw_ostream &OS) const; @@ -109,8 +102,7 @@ public: /// Retrieve a formatted string of the default features for the specified /// target triple. - void getDefaultSubtargetFeatures(const std::string &CPU, - const Triple& Triple); + void getDefaultSubtargetFeatures(const Triple& Triple); }; } // End namespace llvm diff --git a/include/llvm/Target/TargetRegistry.h b/include/llvm/Target/TargetRegistry.h index 071198f..8d44f66 100644 --- a/include/llvm/Target/TargetRegistry.h +++ b/include/llvm/Target/TargetRegistry.h @@ -71,6 +71,7 @@ namespace llvm { typedef MCRegisterInfo *(*MCRegInfoCtorFnTy)(void); typedef TargetMachine *(*TargetMachineCtorTy)(const Target &T, const std::string &TT, + const std::string &CPU, const std::string &Features); typedef AsmPrinter *(*AsmPrinterCtorTy)(TargetMachine &TM, MCStreamer &Streamer); @@ -269,10 +270,11 @@ namespace llvm { /// either the target triple from the module, or the target triple of the /// host if that does not exist. TargetMachine *createTargetMachine(const std::string &Triple, + const std::string &CPU, const std::string &Features) const { if (!TargetMachineCtorFn) return 0; - return TargetMachineCtorFn(*this, Triple, Features); + return TargetMachineCtorFn(*this, Triple, CPU, Features); } /// createAsmBackend - Create a target specific assembly parser. @@ -796,8 +798,9 @@ namespace llvm { private: static TargetMachine *Allocator(const Target &T, const std::string &TT, + const std::string &CPU, const std::string &FS) { - return new TargetMachineImpl(T, TT, FS); + return new TargetMachineImpl(T, TT, CPU, FS); } }; diff --git a/lib/ExecutionEngine/TargetSelect.cpp b/lib/ExecutionEngine/TargetSelect.cpp index 83b1f05..f51aff3 100644 --- a/lib/ExecutionEngine/TargetSelect.cpp +++ b/lib/ExecutionEngine/TargetSelect.cpp @@ -75,9 +75,8 @@ TargetMachine *EngineBuilder::selectTarget(Module *Mod, // Package up features to be passed to target/subtarget std::string FeaturesStr; - if (!MCPU.empty() || !MAttrs.empty()) { + if (!MAttrs.empty()) { SubtargetFeatures Features; - Features.setCPU(MCPU); for (unsigned i = 0; i != MAttrs.size(); ++i) Features.AddFeature(MAttrs[i]); FeaturesStr = Features.getString(); @@ -85,7 +84,7 @@ TargetMachine *EngineBuilder::selectTarget(Module *Mod, // Allocate a target... TargetMachine *Target = - TheTarget->createTargetMachine(TheTriple.getTriple(), FeaturesStr); + TheTarget->createTargetMachine(TheTriple.getTriple(), MCPU, FeaturesStr); assert(Target && "Could not allocate target machine!"); return Target; } diff --git a/lib/MC/MCDisassembler/Disassembler.cpp b/lib/MC/MCDisassembler/Disassembler.cpp index 6e636f0..6d6777e 100644 --- a/lib/MC/MCDisassembler/Disassembler.cpp +++ b/lib/MC/MCDisassembler/Disassembler.cpp @@ -55,11 +55,13 @@ LLVMDisasmContextRef LLVMCreateDisasm(const char *TripleName, void *DisInfo, // Package up features to be passed to target/subtarget std::string FeaturesStr; + std::string CPU; // FIXME: We shouldn't need to do this (and link in codegen). // When we split this out, we should do it in a way that makes // it straightforward to switch subtargets on the fly. - TargetMachine *TM = TheTarget->createTargetMachine(TripleName, FeaturesStr); + TargetMachine *TM = TheTarget->createTargetMachine(TripleName, CPU, + FeaturesStr); assert(TM && "Unable to create target machine!"); // Get the target assembler info needed to setup the context. diff --git a/lib/MC/MCDisassembler/EDDisassembler.cpp b/lib/MC/MCDisassembler/EDDisassembler.cpp index 91c5284..2a46d37 100644 --- a/lib/MC/MCDisassembler/EDDisassembler.cpp +++ b/lib/MC/MCDisassembler/EDDisassembler.cpp @@ -167,9 +167,9 @@ EDDisassembler::EDDisassembler(CPUKey &key) : if (!Tgt) return; + std::string CPU; std::string featureString; - - TargetMachine.reset(Tgt->createTargetMachine(tripleString, + TargetMachine.reset(Tgt->createTargetMachine(tripleString, CPU, featureString)); const TargetRegisterInfo *registerInfo = TargetMachine->getRegisterInfo(); diff --git a/lib/MC/SubtargetFeature.cpp b/lib/MC/SubtargetFeature.cpp index 3ed122a..a6f6b13 100644 --- a/lib/MC/SubtargetFeature.cpp +++ b/lib/MC/SubtargetFeature.cpp @@ -63,6 +63,9 @@ static inline std::string PrependFlag(const std::string &Feature, /// Split - Splits a string of comma separated items in to a vector of strings. /// static void Split(std::vector &V, const std::string &S) { + if (S.empty()) + return; + // Start at beginning of string. size_t Pos = 0; while (true) { @@ -88,7 +91,7 @@ static std::string Join(const std::vector &V) { std::string Result; // If the vector is not empty if (!V.empty()) { - // Start with the CPU feature + // Start with the first feature Result = V[0]; // For each successive feature for (size_t i = 1; i < V.size(); i++) { @@ -186,27 +189,6 @@ void SubtargetFeatures::setString(const std::string &Initial) { Split(Features, LowercaseString(Initial)); } - -/// setCPU - Set the CPU string. Replaces previous setting. Setting to "" -/// clears CPU. -void SubtargetFeatures::setCPU(const std::string &String) { - Features[0] = LowercaseString(String); -} - - -/// setCPUIfNone - Setting CPU string only if no string is set. -/// -void SubtargetFeatures::setCPUIfNone(const std::string &String) { - if (Features[0].empty()) setCPU(String); -} - -/// getCPU - Returns current CPU. -/// -const std::string & SubtargetFeatures::getCPU() const { - return Features[0]; -} - - /// SetImpliedBits - For each feature that is (transitively) implied by this /// feature, set it. /// @@ -245,12 +227,13 @@ void ClearImpliedBits(uint64_t &Bits, const SubtargetFeatureKV *FeatureEntry, } } -/// getBits - Get feature bits. +/// getFeatureBits - Get feature bits a CPU. /// -uint64_t SubtargetFeatures::getBits(const SubtargetFeatureKV *CPUTable, - size_t CPUTableSize, - const SubtargetFeatureKV *FeatureTable, - size_t FeatureTableSize) { +uint64_t SubtargetFeatures::getFeatureBits(const std::string &CPU, + const SubtargetFeatureKV *CPUTable, + size_t CPUTableSize, + const SubtargetFeatureKV *FeatureTable, + size_t FeatureTableSize) { assert(CPUTable && "missing CPU table"); assert(FeatureTable && "missing features table"); #ifndef NDEBUG @@ -266,12 +249,11 @@ uint64_t SubtargetFeatures::getBits(const SubtargetFeatureKV *CPUTable, uint64_t Bits = 0; // Resulting bits // Check if help is needed - if (Features[0] == "help") + if (CPU == "help") Help(CPUTable, CPUTableSize, FeatureTable, FeatureTableSize); // Find CPU entry - const SubtargetFeatureKV *CPUEntry = - Find(Features[0], CPUTable, CPUTableSize); + const SubtargetFeatureKV *CPUEntry = Find(CPU, CPUTable, CPUTableSize); // If there is a match if (CPUEntry) { // Set base feature bits @@ -284,12 +266,12 @@ uint64_t SubtargetFeatures::getBits(const SubtargetFeatureKV *CPUTable, SetImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize); } } else { - errs() << "'" << Features[0] + errs() << "'" << CPU << "' is not a recognized processor for this target" << " (ignoring processor)\n"; } // Iterate through each feature - for (size_t i = 1; i < Features.size(); i++) { + for (size_t i = 0, E = Features.size(); i < E; i++) { const std::string &Feature = Features[i]; // Check for help @@ -323,9 +305,10 @@ uint64_t SubtargetFeatures::getBits(const SubtargetFeatureKV *CPUTable, return Bits; } -/// Get info pointer -void *SubtargetFeatures::getInfo(const SubtargetInfoKV *Table, - size_t TableSize) { +/// Get scheduling itinerary of a CPU. +void *SubtargetFeatures::getItinerary(const std::string &CPU, + const SubtargetInfoKV *Table, + size_t TableSize) { assert(Table && "missing table"); #ifndef NDEBUG for (size_t i = 1; i < TableSize; i++) { @@ -334,12 +317,12 @@ void *SubtargetFeatures::getInfo(const SubtargetInfoKV *Table, #endif // Find entry - const SubtargetInfoKV *Entry = Find(Features[0], Table, TableSize); + const SubtargetInfoKV *Entry = Find(CPU, Table, TableSize); if (Entry) { return Entry->Value; } else { - errs() << "'" << Features[0] + errs() << "'" << CPU << "' is not a recognized processor for this target" << " (ignoring processor)\n"; return NULL; @@ -367,10 +350,7 @@ void SubtargetFeatures::dump() const { /// subtarget. It would be better if we could encode this information /// into the IR. See . /// -void SubtargetFeatures::getDefaultSubtargetFeatures(const std::string &CPU, - const Triple& Triple) { - setCPU(CPU); - +void SubtargetFeatures::getDefaultSubtargetFeatures(const Triple& Triple) { if (Triple.getVendor() == Triple::Apple) { if (Triple.getArch() == Triple::ppc) { // powerpc-apple-* diff --git a/lib/Target/ARM/ARMSubtarget.cpp b/lib/Target/ARM/ARMSubtarget.cpp index f58cb54..cf67497 100644 --- a/lib/Target/ARM/ARMSubtarget.cpp +++ b/lib/Target/ARM/ARMSubtarget.cpp @@ -30,8 +30,8 @@ static cl::opt StrictAlign("arm-strict-align", cl::Hidden, cl::desc("Disallow all unaligned memory accesses")); -ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &FS, - bool isT) +ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &CPU, + const std::string &FS, bool isT) : ARMArchVersion(V4) , ARMProcFamily(Others) , ARMFPUType(None) @@ -56,7 +56,7 @@ ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &FS, , FPOnlySP(false) , AllowsUnalignedMem(false) , stackAlignment(4) - , CPUString("generic") + , CPUString(CPU) , TargetTriple(TT) , TargetABI(ARM_ABI_APCS) { // Determine default and user specified characteristics @@ -64,9 +64,11 @@ ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &FS, // When no arch is specified either by CPU or by attributes, make the default // ARMv4T. const char *ARMArchFeature = ""; + if (CPUString.empty()) + CPUString = "generic"; if (CPUString == "generic" && (FS.empty() || FS == "generic")) { ARMArchVersion = V4T; - ARMArchFeature = ",+v4t"; + ARMArchFeature = "+v4t"; } // Set the boolean corresponding to the current target triple, or the default @@ -85,29 +87,29 @@ ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &FS, unsigned SubVer = TT[Idx]; if (SubVer >= '7' && SubVer <= '9') { ARMArchVersion = V7A; - ARMArchFeature = ",+v7a"; + ARMArchFeature = "+v7a"; if (Len >= Idx+2 && TT[Idx+1] == 'm') { ARMArchVersion = V7M; - ARMArchFeature = ",+v7m"; + ARMArchFeature = "+v7m"; } } else if (SubVer == '6') { ARMArchVersion = V6; - ARMArchFeature = ",+v6"; + ARMArchFeature = "+v6"; if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == '2') { ARMArchVersion = V6T2; - ARMArchFeature = ",+v6t2"; + ARMArchFeature = "+v6t2"; } } else if (SubVer == '5') { ARMArchVersion = V5T; - ARMArchFeature = ",+v5t"; + ARMArchFeature = "+v5t"; if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == 'e') { ARMArchVersion = V5TE; - ARMArchFeature = ",+v5te"; + ARMArchFeature = "+v5te"; } } else if (SubVer == '4') { if (Len >= Idx+2 && TT[Idx+1] == 't') { ARMArchVersion = V4T; - ARMArchFeature = ",+v4t"; + ARMArchFeature = "+v4t"; } else { ARMArchVersion = V4; ARMArchFeature = ""; @@ -129,7 +131,7 @@ ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &FS, FSWithArch = std::string(ARMArchFeature) + FS; else FSWithArch = FS; - CPUString = ParseSubtargetFeatures(FSWithArch, CPUString); + ParseSubtargetFeatures(FSWithArch, CPUString); // After parsing Itineraries, set ItinData.IssueWidth. computeIssueWidth(); diff --git a/lib/Target/ARM/ARMSubtarget.h b/lib/Target/ARM/ARMSubtarget.h index e4bcf3e..7c93173 100644 --- a/lib/Target/ARM/ARMSubtarget.h +++ b/lib/Target/ARM/ARMSubtarget.h @@ -153,7 +153,8 @@ protected: /// This constructor initializes the data members to match that /// of the specified triple. /// - ARMSubtarget(const std::string &TT, const std::string &FS, bool isThumb); + ARMSubtarget(const std::string &TT, const std::string &CPU, + const std::string &FS, bool isThumb); /// getMaxInlineSizeThreshold - Returns the maximum memset / memcpy size /// that still makes it profitable to inline the call. @@ -164,8 +165,7 @@ protected: } /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. - std::string ParseSubtargetFeatures(const std::string &FS, - const std::string &CPU); + void ParseSubtargetFeatures(const std::string &FS, const std::string &CPU); void computeIssueWidth(); diff --git a/lib/Target/ARM/ARMTargetMachine.cpp b/lib/Target/ARM/ARMTargetMachine.cpp index 088427f..80e7d55 100644 --- a/lib/Target/ARM/ARMTargetMachine.cpp +++ b/lib/Target/ARM/ARMTargetMachine.cpp @@ -78,10 +78,11 @@ extern "C" void LLVMInitializeARMTarget() { /// ARMBaseTargetMachine::ARMBaseTargetMachine(const Target &T, const std::string &TT, + const std::string &CPU, const std::string &FS, bool isThumb) : LLVMTargetMachine(T, TT), - Subtarget(TT, FS, isThumb), + Subtarget(TT, CPU, FS, isThumb), JITInfo(), InstrItins(Subtarget.getInstrItineraryData()) { DefRelocModel = getRelocationModel(); @@ -92,8 +93,9 @@ ARMBaseTargetMachine::ARMBaseTargetMachine(const Target &T, } ARMTargetMachine::ARMTargetMachine(const Target &T, const std::string &TT, + const std::string &CPU, const std::string &FS) - : ARMBaseTargetMachine(T, TT, FS, false), InstrInfo(Subtarget), + : ARMBaseTargetMachine(T, TT, CPU, FS, false), InstrInfo(Subtarget), DataLayout(Subtarget.isAPCS_ABI() ? std::string("e-p:32:32-f64:32:64-i64:32:64-" "v128:32:128-v64:32:64-n32") : @@ -109,8 +111,9 @@ ARMTargetMachine::ARMTargetMachine(const Target &T, const std::string &TT, } ThumbTargetMachine::ThumbTargetMachine(const Target &T, const std::string &TT, + const std::string &CPU, const std::string &FS) - : ARMBaseTargetMachine(T, TT, FS, true), + : ARMBaseTargetMachine(T, TT, CPU, FS, true), InstrInfo(Subtarget.hasThumb2() ? ((ARMBaseInstrInfo*)new Thumb2InstrInfo(Subtarget)) : ((ARMBaseInstrInfo*)new Thumb1InstrInfo(Subtarget))), diff --git a/lib/Target/ARM/ARMTargetMachine.h b/lib/Target/ARM/ARMTargetMachine.h index e0aa149..a4a7927 100644 --- a/lib/Target/ARM/ARMTargetMachine.h +++ b/lib/Target/ARM/ARMTargetMachine.h @@ -41,7 +41,8 @@ private: public: ARMBaseTargetMachine(const Target &T, const std::string &TT, - const std::string &FS, bool isThumb); + const std::string &CPU, const std::string &FS, + bool isThumb); virtual ARMJITInfo *getJITInfo() { return &JITInfo; } virtual const ARMSubtarget *getSubtargetImpl() const { return &Subtarget; } @@ -70,7 +71,7 @@ class ARMTargetMachine : public ARMBaseTargetMachine { ARMFrameLowering FrameLowering; public: ARMTargetMachine(const Target &T, const std::string &TT, - const std::string &FS); + const std::string &CPU, const std::string &FS); virtual const ARMRegisterInfo *getRegisterInfo() const { return &InstrInfo.getRegisterInfo(); @@ -109,7 +110,7 @@ class ThumbTargetMachine : public ARMBaseTargetMachine { OwningPtr FrameLowering; public: ThumbTargetMachine(const Target &T, const std::string &TT, - const std::string &FS); + const std::string &CPU, const std::string &FS); /// returns either Thumb1RegisterInfo or Thumb2RegisterInfo virtual const ARMBaseRegisterInfo *getRegisterInfo() const { diff --git a/lib/Target/ARM/AsmParser/ARMAsmLexer.cpp b/lib/Target/ARM/AsmParser/ARMAsmLexer.cpp index 2428ce1..d9a5fa2 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmLexer.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmLexer.cpp @@ -87,8 +87,9 @@ public: : ARMBaseAsmLexer(T, MAI) { std::string tripleString("arm-unknown-unknown"); std::string featureString; + std::string CPU; OwningPtr - targetMachine(T.createTargetMachine(tripleString, featureString)); + targetMachine(T.createTargetMachine(tripleString, CPU, featureString)); InitRegisterMap(targetMachine->getRegisterInfo()); } }; @@ -99,8 +100,9 @@ public: : ARMBaseAsmLexer(T, MAI) { std::string tripleString("thumb-unknown-unknown"); std::string featureString; + std::string CPU; OwningPtr - targetMachine(T.createTargetMachine(tripleString, featureString)); + targetMachine(T.createTargetMachine(tripleString, CPU, featureString)); InitRegisterMap(targetMachine->getRegisterInfo()); } }; diff --git a/lib/Target/Alpha/AlphaSubtarget.cpp b/lib/Target/Alpha/AlphaSubtarget.cpp index bda7104..7080327 100644 --- a/lib/Target/Alpha/AlphaSubtarget.cpp +++ b/lib/Target/Alpha/AlphaSubtarget.cpp @@ -16,10 +16,13 @@ #include "AlphaGenSubtarget.inc" using namespace llvm; -AlphaSubtarget::AlphaSubtarget(const std::string &TT, const std::string &FS) +AlphaSubtarget::AlphaSubtarget(const std::string &TT, const std::string &CPU, + const std::string &FS) : HasCT(false) { - std::string CPU = "generic"; + std::string CPUName = CPU; + if (CPUName.empty()) + CPUName = "generic"; // Parse features string. - ParseSubtargetFeatures(FS, CPU); + ParseSubtargetFeatures(FS, CPUName); } diff --git a/lib/Target/Alpha/AlphaSubtarget.h b/lib/Target/Alpha/AlphaSubtarget.h index ab7d1e0..b1ccf26 100644 --- a/lib/Target/Alpha/AlphaSubtarget.h +++ b/lib/Target/Alpha/AlphaSubtarget.h @@ -31,12 +31,12 @@ public: /// This constructor initializes the data members to match that /// of the specified triple. /// - AlphaSubtarget(const std::string &TT, const std::string &FS); + AlphaSubtarget(const std::string &TT, const std::string &CPU, + const std::string &FS); /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. - std::string ParseSubtargetFeatures(const std::string &FS, - const std::string &CPU); + void ParseSubtargetFeatures(const std::string &FS, const std::string &CPU); bool hasCT() const { return HasCT; } }; diff --git a/lib/Target/Alpha/AlphaTargetMachine.cpp b/lib/Target/Alpha/AlphaTargetMachine.cpp index b53533b..e854ccd 100644 --- a/lib/Target/Alpha/AlphaTargetMachine.cpp +++ b/lib/Target/Alpha/AlphaTargetMachine.cpp @@ -25,11 +25,12 @@ extern "C" void LLVMInitializeAlphaTarget() { } AlphaTargetMachine::AlphaTargetMachine(const Target &T, const std::string &TT, + const std::string &CPU, const std::string &FS) : LLVMTargetMachine(T, TT), DataLayout("e-f128:128:128-n64"), FrameLowering(Subtarget), - Subtarget(TT, FS), + Subtarget(TT, CPU, FS), TLInfo(*this), TSInfo(*this) { setRelocationModel(Reloc::PIC_); diff --git a/lib/Target/Alpha/AlphaTargetMachine.h b/lib/Target/Alpha/AlphaTargetMachine.h index 26238fb..cf00e58 100644 --- a/lib/Target/Alpha/AlphaTargetMachine.h +++ b/lib/Target/Alpha/AlphaTargetMachine.h @@ -37,7 +37,7 @@ class AlphaTargetMachine : public LLVMTargetMachine { public: AlphaTargetMachine(const Target &T, const std::string &TT, - const std::string &FS); + const std::string &CPU, const std::string &FS); virtual const AlphaInstrInfo *getInstrInfo() const { return &InstrInfo; } virtual const TargetFrameLowering *getFrameLowering() const { diff --git a/lib/Target/Blackfin/BlackfinSubtarget.cpp b/lib/Target/Blackfin/BlackfinSubtarget.cpp index e104c52..5092026 100644 --- a/lib/Target/Blackfin/BlackfinSubtarget.cpp +++ b/lib/Target/Blackfin/BlackfinSubtarget.cpp @@ -17,6 +17,7 @@ using namespace llvm; BlackfinSubtarget::BlackfinSubtarget(const std::string &TT, + const std::string &CPU, const std::string &FS) : sdram(false), icplb(false), @@ -30,7 +31,9 @@ BlackfinSubtarget::BlackfinSubtarget(const std::string &TT, wa_killed_mmr(false), wa_rets(false) { - std::string CPU = "generic"; + std::string CPUName = CPU; + if (CPUName.empty()) + CPUName = "generic"; // Parse features string. - ParseSubtargetFeatures(FS, CPU); + ParseSubtargetFeatures(FS, CPUName); } diff --git a/lib/Target/Blackfin/BlackfinSubtarget.h b/lib/Target/Blackfin/BlackfinSubtarget.h index d667fe2..a1a09ec 100644 --- a/lib/Target/Blackfin/BlackfinSubtarget.h +++ b/lib/Target/Blackfin/BlackfinSubtarget.h @@ -32,11 +32,12 @@ namespace llvm { bool wa_killed_mmr; bool wa_rets; public: - BlackfinSubtarget(const std::string &TT, const std::string &FS); + BlackfinSubtarget(const std::string &TT, const std::string &CPU, + const std::string &FS); /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. - std::string ParseSubtargetFeatures(const std::string &FS, + void ParseSubtargetFeatures(const std::string &FS, const std::string &CPU); }; diff --git a/lib/Target/Blackfin/BlackfinTargetMachine.cpp b/lib/Target/Blackfin/BlackfinTargetMachine.cpp index e11920f..477c438 100644 --- a/lib/Target/Blackfin/BlackfinTargetMachine.cpp +++ b/lib/Target/Blackfin/BlackfinTargetMachine.cpp @@ -26,10 +26,11 @@ extern "C" void LLVMInitializeBlackfinTarget() { BlackfinTargetMachine::BlackfinTargetMachine(const Target &T, const std::string &TT, + const std::string &CPU, const std::string &FS) : LLVMTargetMachine(T, TT), DataLayout("e-p:32:32-i64:32-f64:32-n32"), - Subtarget(TT, FS), + Subtarget(TT, CPU, FS), TLInfo(*this), TSInfo(*this), InstrInfo(Subtarget), diff --git a/lib/Target/Blackfin/BlackfinTargetMachine.h b/lib/Target/Blackfin/BlackfinTargetMachine.h index 29b2b17..bd7dc84 100644 --- a/lib/Target/Blackfin/BlackfinTargetMachine.h +++ b/lib/Target/Blackfin/BlackfinTargetMachine.h @@ -36,7 +36,7 @@ namespace llvm { BlackfinIntrinsicInfo IntrinsicInfo; public: BlackfinTargetMachine(const Target &T, const std::string &TT, - const std::string &FS); + const std::string &CPU, const std::string &FS); virtual const BlackfinInstrInfo *getInstrInfo() const { return &InstrInfo; } virtual const TargetFrameLowering *getFrameLowering() const { diff --git a/lib/Target/CBackend/CTargetMachine.h b/lib/Target/CBackend/CTargetMachine.h index 6fed195..88cc8eb 100644 --- a/lib/Target/CBackend/CTargetMachine.h +++ b/lib/Target/CBackend/CTargetMachine.h @@ -20,7 +20,8 @@ namespace llvm { struct CTargetMachine : public TargetMachine { - CTargetMachine(const Target &T, const std::string &TT, const std::string &FS) + CTargetMachine(const Target &T, const std::string &TT, + const std::string &CPU, const std::string &FS) : TargetMachine(T) {} virtual bool addPassesToEmitFile(PassManagerBase &PM, diff --git a/lib/Target/CellSPU/SPUSubtarget.cpp b/lib/Target/CellSPU/SPUSubtarget.cpp index 07c8352..a1a9f51 100644 --- a/lib/Target/CellSPU/SPUSubtarget.cpp +++ b/lib/Target/CellSPU/SPUSubtarget.cpp @@ -19,7 +19,8 @@ using namespace llvm; -SPUSubtarget::SPUSubtarget(const std::string &TT, const std::string &FS) : +SPUSubtarget::SPUSubtarget(const std::string &TT, const std::string &CPU, + const std::string &FS) : StackAlignment(16), ProcDirective(SPU::DEFAULT_PROC), UseLargeMem(false) diff --git a/lib/Target/CellSPU/SPUSubtarget.h b/lib/Target/CellSPU/SPUSubtarget.h index 39b2d86..69a60db 100644 --- a/lib/Target/CellSPU/SPUSubtarget.h +++ b/lib/Target/CellSPU/SPUSubtarget.h @@ -49,12 +49,12 @@ namespace llvm { /// This constructor initializes the data members to match that /// of the specified triple. /// - SPUSubtarget(const std::string &TT, const std::string &FS); + SPUSubtarget(const std::string &TT, const std::string &CPU, + const std::string &FS); /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. - std::string ParseSubtargetFeatures(const std::string &FS, - const std::string &CPU); + void ParseSubtargetFeatures(const std::string &FS, const std::string &CPU); /// SetJITMode - This is called to inform the subtarget info that we are /// producing code for the JIT. diff --git a/lib/Target/CellSPU/SPUTargetMachine.cpp b/lib/Target/CellSPU/SPUTargetMachine.cpp index 3ed7361..f04e982 100644 --- a/lib/Target/CellSPU/SPUTargetMachine.cpp +++ b/lib/Target/CellSPU/SPUTargetMachine.cpp @@ -35,9 +35,9 @@ SPUFrameLowering::getCalleeSaveSpillSlots(unsigned &NumEntries) const { } SPUTargetMachine::SPUTargetMachine(const Target &T, const std::string &TT, - const std::string &FS) + const std::string &CPU,const std::string &FS) : LLVMTargetMachine(T, TT), - Subtarget(TT, FS), + Subtarget(TT, CPU, FS), DataLayout(Subtarget.getTargetDataString()), InstrInfo(*this), FrameLowering(Subtarget), diff --git a/lib/Target/CellSPU/SPUTargetMachine.h b/lib/Target/CellSPU/SPUTargetMachine.h index 75abd5e..d96f86d 100644 --- a/lib/Target/CellSPU/SPUTargetMachine.h +++ b/lib/Target/CellSPU/SPUTargetMachine.h @@ -39,7 +39,7 @@ class SPUTargetMachine : public LLVMTargetMachine { InstrItineraryData InstrItins; public: SPUTargetMachine(const Target &T, const std::string &TT, - const std::string &FS); + const std::string &CPU, const std::string &FS); /// Return the subtarget implementation object virtual const SPUSubtarget *getSubtargetImpl() const { diff --git a/lib/Target/CppBackend/CPPTargetMachine.h b/lib/Target/CppBackend/CPPTargetMachine.h index e42166e..8023e13 100644 --- a/lib/Target/CppBackend/CPPTargetMachine.h +++ b/lib/Target/CppBackend/CPPTargetMachine.h @@ -23,7 +23,7 @@ class formatted_raw_ostream; struct CPPTargetMachine : public TargetMachine { CPPTargetMachine(const Target &T, const std::string &TT, - const std::string &FS) + const std::string &CPU, const std::string &FS) : TargetMachine(T) {} virtual bool addPassesToEmitFile(PassManagerBase &PM, diff --git a/lib/Target/MBlaze/AsmParser/MBlazeAsmLexer.cpp b/lib/Target/MBlaze/AsmParser/MBlazeAsmLexer.cpp index 1903796..1596596 100644 --- a/lib/Target/MBlaze/AsmParser/MBlazeAsmLexer.cpp +++ b/lib/Target/MBlaze/AsmParser/MBlazeAsmLexer.cpp @@ -86,8 +86,9 @@ namespace { : MBlazeBaseAsmLexer(T, MAI) { std::string tripleString("mblaze-unknown-unknown"); std::string featureString; + std::string CPU; OwningPtr - targetMachine(T.createTargetMachine(tripleString, featureString)); + targetMachine(T.createTargetMachine(tripleString, CPU, featureString)); InitRegisterMap(targetMachine->getRegisterInfo()); } }; diff --git a/lib/Target/MBlaze/MBlazeSubtarget.cpp b/lib/Target/MBlaze/MBlazeSubtarget.cpp index a80744a..034b5ce 100644 --- a/lib/Target/MBlaze/MBlazeSubtarget.cpp +++ b/lib/Target/MBlaze/MBlazeSubtarget.cpp @@ -18,18 +18,22 @@ #include "llvm/Support/CommandLine.h" using namespace llvm; -MBlazeSubtarget::MBlazeSubtarget(const std::string &TT, const std::string &FS): +MBlazeSubtarget::MBlazeSubtarget(const std::string &TT, + const std::string &CPU, + const std::string &FS): HasBarrel(false), HasDiv(false), HasMul(false), HasPatCmp(false), HasFPU(false), HasMul64(false), HasSqrt(false) { // Parse features string. - std::string CPU = "mblaze"; - CPU = ParseSubtargetFeatures(FS, CPU); + std::string CPUName = CPU; + if (CPUName.empty()) + CPUName = "mblaze"; + ParseSubtargetFeatures(FS, CPUName); // Only use instruction scheduling if the selected CPU has an instruction // itinerary (the default CPU is the only one that doesn't). - HasItin = CPU != "mblaze"; - DEBUG(dbgs() << "CPU " << CPU << "(" << HasItin << ")\n"); + HasItin = CPUName != "mblaze"; + DEBUG(dbgs() << "CPU " << CPUName << "(" << HasItin << ")\n"); // Compute the issue width of the MBlaze itineraries computeIssueWidth(); diff --git a/lib/Target/MBlaze/MBlazeSubtarget.h b/lib/Target/MBlaze/MBlazeSubtarget.h index 342b2fb..f5e0b4c 100644 --- a/lib/Target/MBlaze/MBlazeSubtarget.h +++ b/lib/Target/MBlaze/MBlazeSubtarget.h @@ -38,12 +38,12 @@ public: /// This constructor initializes the data members to match that /// of the specified triple. - MBlazeSubtarget(const std::string &TT, const std::string &FS); + MBlazeSubtarget(const std::string &TT, const std::string &CPU, + const std::string &FS); /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. - std::string ParseSubtargetFeatures(const std::string &FS, - const std::string &CPU); + void ParseSubtargetFeatures(const std::string &FS, const std::string &CPU); /// Compute the number of maximum number of issues per cycle for the /// MBlaze scheduling itineraries. diff --git a/lib/Target/MBlaze/MBlazeTargetMachine.cpp b/lib/Target/MBlaze/MBlazeTargetMachine.cpp index df34a83..1cbd2d4 100644 --- a/lib/Target/MBlaze/MBlazeTargetMachine.cpp +++ b/lib/Target/MBlaze/MBlazeTargetMachine.cpp @@ -80,9 +80,9 @@ extern "C" void LLVMInitializeMBlazeTarget() { // an easier handling. MBlazeTargetMachine:: MBlazeTargetMachine(const Target &T, const std::string &TT, - const std::string &FS): + const std::string &CPU, const std::string &FS): LLVMTargetMachine(T, TT), - Subtarget(TT, FS), + Subtarget(TT, CPU, FS), DataLayout("E-p:32:32:32-i8:8:8-i16:16:16"), InstrInfo(*this), FrameLowering(Subtarget), diff --git a/lib/Target/MBlaze/MBlazeTargetMachine.h b/lib/Target/MBlaze/MBlazeTargetMachine.h index 48ce37a..cd6caaf 100644 --- a/lib/Target/MBlaze/MBlazeTargetMachine.h +++ b/lib/Target/MBlaze/MBlazeTargetMachine.h @@ -42,7 +42,7 @@ namespace llvm { public: MBlazeTargetMachine(const Target &T, const std::string &TT, - const std::string &FS); + const std::string &CPU, const std::string &FS); virtual const MBlazeInstrInfo *getInstrInfo() const { return &InstrInfo; } diff --git a/lib/Target/MSP430/MSP430Subtarget.cpp b/lib/Target/MSP430/MSP430Subtarget.cpp index 1346cb9..a257abe 100644 --- a/lib/Target/MSP430/MSP430Subtarget.cpp +++ b/lib/Target/MSP430/MSP430Subtarget.cpp @@ -17,7 +17,9 @@ using namespace llvm; -MSP430Subtarget::MSP430Subtarget(const std::string &TT, const std::string &FS) { +MSP430Subtarget::MSP430Subtarget(const std::string &TT, + const std::string &CPUIgnored, + const std::string &FS) { std::string CPU = "generic"; // Parse features string. diff --git a/lib/Target/MSP430/MSP430Subtarget.h b/lib/Target/MSP430/MSP430Subtarget.h index 1070544..f36428a 100644 --- a/lib/Target/MSP430/MSP430Subtarget.h +++ b/lib/Target/MSP430/MSP430Subtarget.h @@ -26,12 +26,12 @@ public: /// This constructor initializes the data members to match that /// of the specified triple. /// - MSP430Subtarget(const std::string &TT, const std::string &FS); + MSP430Subtarget(const std::string &TT, const std::string &CPU, + const std::string &FS); /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. - std::string ParseSubtargetFeatures(const std::string &FS, - const std::string &CPU); + void ParseSubtargetFeatures(const std::string &FS, const std::string &CPU); }; } // End llvm namespace diff --git a/lib/Target/MSP430/MSP430TargetMachine.cpp b/lib/Target/MSP430/MSP430TargetMachine.cpp index fba9536..3ee5e6a 100644 --- a/lib/Target/MSP430/MSP430TargetMachine.cpp +++ b/lib/Target/MSP430/MSP430TargetMachine.cpp @@ -28,9 +28,10 @@ extern "C" void LLVMInitializeMSP430Target() { MSP430TargetMachine::MSP430TargetMachine(const Target &T, const std::string &TT, + const std::string &CPU, const std::string &FS) : LLVMTargetMachine(T, TT), - Subtarget(TT, FS), + Subtarget(TT, CPU, FS), // FIXME: Check TargetData string. DataLayout("e-p:16:16:16-i8:8:8-i16:16:16-i32:16:32-n8:16"), InstrInfo(*this), TLInfo(*this), TSInfo(*this), diff --git a/lib/Target/MSP430/MSP430TargetMachine.h b/lib/Target/MSP430/MSP430TargetMachine.h index cee3b04..2a9eea0 100644 --- a/lib/Target/MSP430/MSP430TargetMachine.h +++ b/lib/Target/MSP430/MSP430TargetMachine.h @@ -39,7 +39,7 @@ class MSP430TargetMachine : public LLVMTargetMachine { public: MSP430TargetMachine(const Target &T, const std::string &TT, - const std::string &FS); + const std::string &CPU, const std::string &FS); virtual const TargetFrameLowering *getFrameLowering() const { return &FrameLowering; diff --git a/lib/Target/Mips/MipsSubtarget.cpp b/lib/Target/Mips/MipsSubtarget.cpp index 70747f5..306ea11 100644 --- a/lib/Target/Mips/MipsSubtarget.cpp +++ b/lib/Target/Mips/MipsSubtarget.cpp @@ -16,18 +16,20 @@ #include "MipsGenSubtarget.inc" using namespace llvm; -MipsSubtarget::MipsSubtarget(const std::string &TT, const std::string &FS, - bool little) : +MipsSubtarget::MipsSubtarget(const std::string &TT, const std::string &CPU, + const std::string &FS, bool little) : MipsArchVersion(Mips1), MipsABI(O32), IsLittle(little), IsSingleFloat(false), IsFP64bit(false), IsGP64bit(false), HasVFPU(false), IsLinux(true), HasSEInReg(false), HasCondMov(false), HasMulDivAdd(false), HasMinMax(false), HasSwap(false), HasBitCount(false) { - std::string CPU = "mips1"; + std::string CPUName = CPU; + if (CPUName.empty()) + CPUName = "mips1"; MipsArchVersion = Mips1; // Parse features string. - ParseSubtargetFeatures(FS, CPU); + ParseSubtargetFeatures(FS, CPUName); // Is the target system Linux ? if (TT.find("linux") == std::string::npos) diff --git a/lib/Target/Mips/MipsSubtarget.h b/lib/Target/Mips/MipsSubtarget.h index f09df6b..8acbf5b 100644 --- a/lib/Target/Mips/MipsSubtarget.h +++ b/lib/Target/Mips/MipsSubtarget.h @@ -91,12 +91,12 @@ public: /// This constructor initializes the data members to match that /// of the specified triple. - MipsSubtarget(const std::string &TT, const std::string &FS, bool little); + MipsSubtarget(const std::string &TT, const std::string &CPU, + const std::string &FS, bool little); /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. - std::string ParseSubtargetFeatures(const std::string &FS, - const std::string &CPU); + void ParseSubtargetFeatures(const std::string &FS, const std::string &CPU); bool isMips1() const { return MipsArchVersion == Mips1; } bool isMips32() const { return MipsArchVersion >= Mips32; } diff --git a/lib/Target/Mips/MipsTargetMachine.cpp b/lib/Target/Mips/MipsTargetMachine.cpp index cfbb92c..88ce3b8 100644 --- a/lib/Target/Mips/MipsTargetMachine.cpp +++ b/lib/Target/Mips/MipsTargetMachine.cpp @@ -34,10 +34,11 @@ extern "C" void LLVMInitializeMipsTarget() { // an easier handling. // Using CodeModel::Large enables different CALL behavior. MipsTargetMachine:: -MipsTargetMachine(const Target &T, const std::string &TT, const std::string &FS, +MipsTargetMachine(const Target &T, const std::string &TT, + const std::string &CPU, const std::string &FS, bool isLittle=false): LLVMTargetMachine(T, TT), - Subtarget(TT, FS, isLittle), + Subtarget(TT, CPU, FS, isLittle), DataLayout(isLittle ? std::string("e-p:32:32:32-i8:8:32-i16:16:32-i64:64:64-n32") : std::string("E-p:32:32:32-i8:8:32-i16:16:32-i64:64:64-n32")), @@ -55,8 +56,8 @@ MipsTargetMachine(const Target &T, const std::string &TT, const std::string &FS, MipselTargetMachine:: MipselTargetMachine(const Target &T, const std::string &TT, - const std::string &FS) : - MipsTargetMachine(T, TT, FS, true) {} + const std::string &CPU, const std::string &FS) : + MipsTargetMachine(T, TT, CPU, FS, true) {} // Install an instruction selector pass using // the ISelDag to gen Mips code. diff --git a/lib/Target/Mips/MipsTargetMachine.h b/lib/Target/Mips/MipsTargetMachine.h index 102dd85..a021af2 100644 --- a/lib/Target/Mips/MipsTargetMachine.h +++ b/lib/Target/Mips/MipsTargetMachine.h @@ -35,7 +35,8 @@ namespace llvm { MipsSelectionDAGInfo TSInfo; public: MipsTargetMachine(const Target &T, const std::string &TT, - const std::string &FS, bool isLittle); + const std::string &CPU, const std::string &FS, + bool isLittle); virtual const MipsInstrInfo *getInstrInfo() const { return &InstrInfo; } @@ -73,7 +74,7 @@ namespace llvm { class MipselTargetMachine : public MipsTargetMachine { public: MipselTargetMachine(const Target &T, const std::string &TT, - const std::string &FS); + const std::string &CPU, const std::string &FS); }; } // End llvm namespace diff --git a/lib/Target/PTX/PTXSubtarget.cpp b/lib/Target/PTX/PTXSubtarget.cpp index 77e3431..f8941b6 100644 --- a/lib/Target/PTX/PTXSubtarget.cpp +++ b/lib/Target/PTX/PTXSubtarget.cpp @@ -16,14 +16,16 @@ using namespace llvm; -PTXSubtarget::PTXSubtarget(const std::string &TT, const std::string &FS, - bool is64Bit) +PTXSubtarget::PTXSubtarget(const std::string &TT, const std::string &CPU, + const std::string &FS, bool is64Bit) : PTXTarget(PTX_COMPUTE_1_0), PTXVersion(PTX_VERSION_2_0), SupportsDouble(false), SupportsFMA(true), Is64Bit(is64Bit) { - std::string TARGET = "generic"; + std::string TARGET = CPU; + if (TARGET.empty()) + TARGET = "generic"; ParseSubtargetFeatures(FS, TARGET); } diff --git a/lib/Target/PTX/PTXSubtarget.h b/lib/Target/PTX/PTXSubtarget.h index 58d192b..6d03377 100644 --- a/lib/Target/PTX/PTXSubtarget.h +++ b/lib/Target/PTX/PTXSubtarget.h @@ -74,7 +74,8 @@ namespace llvm { public: - PTXSubtarget(const std::string &TT, const std::string &FS, bool is64Bit); + PTXSubtarget(const std::string &TT, const std::string &CPU, + const std::string &FS, bool is64Bit); // Target architecture accessors std::string getTargetString() const; @@ -108,8 +109,8 @@ namespace llvm { (PTXTarget >= PTX_COMPUTE_2_0 && PTXTarget < PTX_LAST_COMPUTE); } - std::string ParseSubtargetFeatures(const std::string &FS, - const std::string &CPU); + void ParseSubtargetFeatures(const std::string &FS, + const std::string &CPU); }; // class PTXSubtarget } // namespace llvm diff --git a/lib/Target/PTX/PTXTargetMachine.cpp b/lib/Target/PTX/PTXTargetMachine.cpp index 1b737c9..ef648c6 100644 --- a/lib/Target/PTX/PTXTargetMachine.cpp +++ b/lib/Target/PTX/PTXTargetMachine.cpp @@ -52,11 +52,12 @@ namespace { // DataLayout and FrameLowering are filled with dummy data PTXTargetMachine::PTXTargetMachine(const Target &T, const std::string &TT, + const std::string &CPU, const std::string &FS, bool is64Bit) : LLVMTargetMachine(T, TT), DataLayout(is64Bit ? DataLayout64 : DataLayout32), - Subtarget(TT, FS, is64Bit), + Subtarget(TT, CPU, FS, is64Bit), FrameLowering(Subtarget), InstrInfo(*this), TLInfo(*this) { @@ -64,14 +65,16 @@ PTXTargetMachine::PTXTargetMachine(const Target &T, PTX32TargetMachine::PTX32TargetMachine(const Target &T, const std::string& TT, + const std::string& CPU, const std::string& FS) - : PTXTargetMachine(T, TT, FS, false) { + : PTXTargetMachine(T, TT, CPU, FS, false) { } PTX64TargetMachine::PTX64TargetMachine(const Target &T, const std::string& TT, + const std::string& CPU, const std::string& FS) - : PTXTargetMachine(T, TT, FS, true) { + : PTXTargetMachine(T, TT, CPU, FS, true) { } bool PTXTargetMachine::addInstSelector(PassManagerBase &PM, diff --git a/lib/Target/PTX/PTXTargetMachine.h b/lib/Target/PTX/PTXTargetMachine.h index 149be8e..ae42153 100644 --- a/lib/Target/PTX/PTXTargetMachine.h +++ b/lib/Target/PTX/PTXTargetMachine.h @@ -33,7 +33,8 @@ class PTXTargetMachine : public LLVMTargetMachine { public: PTXTargetMachine(const Target &T, const std::string &TT, - const std::string &FS, bool is64Bit); + const std::string &CPU, const std::string &FS, + bool is64Bit); virtual const TargetData *getTargetData() const { return &DataLayout; } @@ -61,14 +62,14 @@ class PTX32TargetMachine : public PTXTargetMachine { public: PTX32TargetMachine(const Target &T, const std::string &TT, - const std::string& FS); + const std::string& CPU, const std::string& FS); }; // class PTX32TargetMachine class PTX64TargetMachine : public PTXTargetMachine { public: PTX64TargetMachine(const Target &T, const std::string &TT, - const std::string& FS); + const std::string& CPU, const std::string& FS); }; // class PTX32TargetMachine } // namespace llvm diff --git a/lib/Target/PowerPC/PPCSubtarget.cpp b/lib/Target/PowerPC/PPCSubtarget.cpp index 5f3aa23..bcc4c21 100644 --- a/lib/Target/PowerPC/PPCSubtarget.cpp +++ b/lib/Target/PowerPC/PPCSubtarget.cpp @@ -57,8 +57,8 @@ static const char *GetCurrentPowerPCCPU() { #endif -PPCSubtarget::PPCSubtarget(const std::string &TT, const std::string &FS, - bool is64Bit) +PPCSubtarget::PPCSubtarget(const std::string &TT, const std::string &CPU, + const std::string &FS, bool is64Bit) : StackAlignment(16) , DarwinDirective(PPC::DIR_NONE) , IsGigaProcessor(false) @@ -73,13 +73,16 @@ PPCSubtarget::PPCSubtarget(const std::string &TT, const std::string &FS, , TargetTriple(TT) { // Determine default and user specified characteristics - std::string CPU = "generic"; + std::string CPUName = CPU; + if (CPUName.empty()) + CPUName = "generic"; #if defined(__APPLE__) - CPU = GetCurrentPowerPCCPU(); + if (CPUName == "generic") + CPUName = GetCurrentPowerPCCPU(); #endif // Parse features string. - ParseSubtargetFeatures(FS, CPU); + ParseSubtargetFeatures(FS, CPUName); // If we are generating code for ppc64, verify that options make sense. if (is64Bit) { diff --git a/lib/Target/PowerPC/PPCSubtarget.h b/lib/Target/PowerPC/PPCSubtarget.h index 799bb3d..55c3fef 100644 --- a/lib/Target/PowerPC/PPCSubtarget.h +++ b/lib/Target/PowerPC/PPCSubtarget.h @@ -72,12 +72,12 @@ public: /// This constructor initializes the data members to match that /// of the specified triple. /// - PPCSubtarget(const std::string &TT, const std::string &FS, bool is64Bit); + PPCSubtarget(const std::string &TT, const std::string &CPU, + const std::string &FS, bool is64Bit); /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. - std::string ParseSubtargetFeatures(const std::string &FS, - const std::string &CPU); + void ParseSubtargetFeatures(const std::string &FS, const std::string &CPU); /// SetJITMode - This is called to inform the subtarget info that we are diff --git a/lib/Target/PowerPC/PPCTargetMachine.cpp b/lib/Target/PowerPC/PPCTargetMachine.cpp index d27e54e..09fc1e3 100644 --- a/lib/Target/PowerPC/PPCTargetMachine.cpp +++ b/lib/Target/PowerPC/PPCTargetMachine.cpp @@ -67,9 +67,10 @@ extern "C" void LLVMInitializePowerPCTarget() { PPCTargetMachine::PPCTargetMachine(const Target &T, const std::string &TT, + const std::string &CPU, const std::string &FS, bool is64Bit) : LLVMTargetMachine(T, TT), - Subtarget(TT, FS, is64Bit), + Subtarget(TT, CPU, FS, is64Bit), DataLayout(Subtarget.getTargetDataString()), InstrInfo(*this), FrameLowering(Subtarget), JITInfo(*this, is64Bit), TLInfo(*this), TSInfo(*this), @@ -88,14 +89,16 @@ PPCTargetMachine::PPCTargetMachine(const Target &T, const std::string &TT, bool PPCTargetMachine::getEnableTailMergeDefault() const { return false; } PPC32TargetMachine::PPC32TargetMachine(const Target &T, const std::string &TT, + const std::string &CPU, const std::string &FS) - : PPCTargetMachine(T, TT, FS, false) { + : PPCTargetMachine(T, TT, CPU, FS, false) { } PPC64TargetMachine::PPC64TargetMachine(const Target &T, const std::string &TT, + const std::string &CPU, const std::string &FS) - : PPCTargetMachine(T, TT, FS, true) { + : PPCTargetMachine(T, TT, CPU, FS, true) { } diff --git a/lib/Target/PowerPC/PPCTargetMachine.h b/lib/Target/PowerPC/PPCTargetMachine.h index 2d24989..baf07e3 100644 --- a/lib/Target/PowerPC/PPCTargetMachine.h +++ b/lib/Target/PowerPC/PPCTargetMachine.h @@ -41,7 +41,8 @@ class PPCTargetMachine : public LLVMTargetMachine { public: PPCTargetMachine(const Target &T, const std::string &TT, - const std::string &FS, bool is64Bit); + const std::string &CPU, const std::string &FS, + bool is64Bit); virtual const PPCInstrInfo *getInstrInfo() const { return &InstrInfo; } virtual const PPCFrameLowering *getFrameLowering() const { @@ -77,7 +78,7 @@ public: class PPC32TargetMachine : public PPCTargetMachine { public: PPC32TargetMachine(const Target &T, const std::string &TT, - const std::string &FS); + const std::string &CPU, const std::string &FS); }; /// PPC64TargetMachine - PowerPC 64-bit target machine. @@ -85,7 +86,7 @@ public: class PPC64TargetMachine : public PPCTargetMachine { public: PPC64TargetMachine(const Target &T, const std::string &TT, - const std::string &FS); + const std::string &CPU, const std::string &FS); }; } // end namespace llvm diff --git a/lib/Target/Sparc/SparcSubtarget.cpp b/lib/Target/Sparc/SparcSubtarget.cpp index ce11af1..06bfc64 100644 --- a/lib/Target/Sparc/SparcSubtarget.cpp +++ b/lib/Target/Sparc/SparcSubtarget.cpp @@ -15,20 +15,23 @@ #include "SparcGenSubtarget.inc" using namespace llvm; -SparcSubtarget::SparcSubtarget(const std::string &TT, const std::string &FS, - bool is64Bit) : +SparcSubtarget::SparcSubtarget(const std::string &TT, const std::string &CPU, + const std::string &FS, bool is64Bit) : IsV9(false), V8DeprecatedInsts(false), IsVIS(false), Is64Bit(is64Bit) { // Determine default and user specified characteristics - const char *CPU = "v8"; - if (is64Bit) { - CPU = "v9"; - IsV9 = true; + std::string CPUName = CPU; + if (CPUName.empty()) { + if (is64Bit) + CPUName = "v9"; + else + CPUName = "v8"; } + IsV9 = CPUName == "v9"; // Parse features string. - ParseSubtargetFeatures(FS, CPU); + ParseSubtargetFeatures(FS, CPUName); } diff --git a/lib/Target/Sparc/SparcSubtarget.h b/lib/Target/Sparc/SparcSubtarget.h index cec0ab4..eabf390 100644 --- a/lib/Target/Sparc/SparcSubtarget.h +++ b/lib/Target/Sparc/SparcSubtarget.h @@ -26,7 +26,8 @@ class SparcSubtarget : public TargetSubtarget { bool Is64Bit; public: - SparcSubtarget(const std::string &TT, const std::string &FS, bool is64bit); + SparcSubtarget(const std::string &TT, const std::string &CPU, + const std::string &FS, bool is64bit); bool isV9() const { return IsV9; } bool isVIS() const { return IsVIS; } @@ -34,8 +35,7 @@ public: /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. - std::string ParseSubtargetFeatures(const std::string &FS, - const std::string &CPU); + void ParseSubtargetFeatures(const std::string &FS, const std::string &CPU); bool is64Bit() const { return Is64Bit; } std::string getDataLayout() const { diff --git a/lib/Target/Sparc/SparcTargetMachine.cpp b/lib/Target/Sparc/SparcTargetMachine.cpp index b84eab5..792dd94 100644 --- a/lib/Target/Sparc/SparcTargetMachine.cpp +++ b/lib/Target/Sparc/SparcTargetMachine.cpp @@ -30,9 +30,10 @@ extern "C" void LLVMInitializeSparcTarget() { /// SparcTargetMachine ctor - Create an ILP32 architecture model /// SparcTargetMachine::SparcTargetMachine(const Target &T, const std::string &TT, + const std::string &CPU, const std::string &FS, bool is64bit) : LLVMTargetMachine(T, TT), - Subtarget(TT, FS, is64bit), + Subtarget(TT, CPU, FS, is64bit), DataLayout(Subtarget.getDataLayout()), TLInfo(*this), TSInfo(*this), InstrInfo(Subtarget), FrameLowering(Subtarget) { @@ -56,12 +57,14 @@ bool SparcTargetMachine::addPreEmitPass(PassManagerBase &PM, SparcV8TargetMachine::SparcV8TargetMachine(const Target &T, const std::string &TT, + const std::string &CPU, const std::string &FS) - : SparcTargetMachine(T, TT, FS, false) { + : SparcTargetMachine(T, TT, CPU, FS, false) { } SparcV9TargetMachine::SparcV9TargetMachine(const Target &T, const std::string &TT, + const std::string &CPU, const std::string &FS) - : SparcTargetMachine(T, TT, FS, true) { + : SparcTargetMachine(T, TT, CPU, FS, true) { } diff --git a/lib/Target/Sparc/SparcTargetMachine.h b/lib/Target/Sparc/SparcTargetMachine.h index c4bb6bd..799fc49 100644 --- a/lib/Target/Sparc/SparcTargetMachine.h +++ b/lib/Target/Sparc/SparcTargetMachine.h @@ -34,7 +34,8 @@ class SparcTargetMachine : public LLVMTargetMachine { SparcFrameLowering FrameLowering; public: SparcTargetMachine(const Target &T, const std::string &TT, - const std::string &FS, bool is64bit); + const std::string &CPU, const std::string &FS, + bool is64bit); virtual const SparcInstrInfo *getInstrInfo() const { return &InstrInfo; } virtual const TargetFrameLowering *getFrameLowering() const { @@ -62,7 +63,7 @@ public: class SparcV8TargetMachine : public SparcTargetMachine { public: SparcV8TargetMachine(const Target &T, const std::string &TT, - const std::string &FS); + const std::string &CPU, const std::string &FS); }; /// SparcV9TargetMachine - Sparc 64-bit target machine @@ -70,7 +71,7 @@ public: class SparcV9TargetMachine : public SparcTargetMachine { public: SparcV9TargetMachine(const Target &T, const std::string &TT, - const std::string &FS); + const std::string &CPU, const std::string &FS); }; } // end namespace llvm diff --git a/lib/Target/SystemZ/SystemZSubtarget.cpp b/lib/Target/SystemZ/SystemZSubtarget.cpp index a8b5e1f..95521b2 100644 --- a/lib/Target/SystemZ/SystemZSubtarget.cpp +++ b/lib/Target/SystemZ/SystemZSubtarget.cpp @@ -20,12 +20,15 @@ using namespace llvm; SystemZSubtarget::SystemZSubtarget(const std::string &TT, + const std::string &CPU, const std::string &FS): HasZ10Insts(false) { - std::string CPU = "z9"; + std::string CPUName = CPU; + if (CPUName.empty()) + CPUName = "z9"; // Parse features string. - ParseSubtargetFeatures(FS, CPU); + ParseSubtargetFeatures(FS, CPUName); } /// True if accessing the GV requires an extra load. diff --git a/lib/Target/SystemZ/SystemZSubtarget.h b/lib/Target/SystemZ/SystemZSubtarget.h index 405d6e9..453471c 100644 --- a/lib/Target/SystemZ/SystemZSubtarget.h +++ b/lib/Target/SystemZ/SystemZSubtarget.h @@ -28,12 +28,12 @@ public: /// This constructor initializes the data members to match that /// of the specified triple. /// - SystemZSubtarget(const std::string &TT, const std::string &FS); + SystemZSubtarget(const std::string &TT, const std::string &CPU, + const std::string &FS); /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. - std::string ParseSubtargetFeatures(const std::string &FS, - const std::string &CPU); + void ParseSubtargetFeatures(const std::string &FS, const std::string &CPU); bool isZ10() const { return HasZ10Insts; } diff --git a/lib/Target/SystemZ/SystemZTargetMachine.cpp b/lib/Target/SystemZ/SystemZTargetMachine.cpp index 1603899..3329ce6 100644 --- a/lib/Target/SystemZ/SystemZTargetMachine.cpp +++ b/lib/Target/SystemZ/SystemZTargetMachine.cpp @@ -24,9 +24,10 @@ extern "C" void LLVMInitializeSystemZTarget() { /// SystemZTargetMachine::SystemZTargetMachine(const Target &T, const std::string &TT, + const std::string &CPU, const std::string &FS) : LLVMTargetMachine(T, TT), - Subtarget(TT, FS), + Subtarget(TT, CPU, FS), DataLayout("E-p:64:64:64-i8:8:16-i16:16:16-i32:32:32-i64:64:64-f32:32:32" "-f64:64:64-f128:128:128-a0:16:16-n32:64"), InstrInfo(*this), TLInfo(*this), TSInfo(*this), diff --git a/lib/Target/SystemZ/SystemZTargetMachine.h b/lib/Target/SystemZ/SystemZTargetMachine.h index 524f83d..e40b556 100644 --- a/lib/Target/SystemZ/SystemZTargetMachine.h +++ b/lib/Target/SystemZ/SystemZTargetMachine.h @@ -38,7 +38,7 @@ class SystemZTargetMachine : public LLVMTargetMachine { SystemZFrameLowering FrameLowering; public: SystemZTargetMachine(const Target &T, const std::string &TT, - const std::string &FS); + const std::string &CPU, const std::string &FS); virtual const TargetFrameLowering *getFrameLowering() const { return &FrameLowering; diff --git a/lib/Target/X86/X86Subtarget.cpp b/lib/Target/X86/X86Subtarget.cpp index adcf69a..d7f630c 100644 --- a/lib/Target/X86/X86Subtarget.cpp +++ b/lib/Target/X86/X86Subtarget.cpp @@ -284,7 +284,8 @@ void X86Subtarget::AutoDetectSubtargetFeatures() { } } -X86Subtarget::X86Subtarget(const std::string &TT, const std::string &FS, +X86Subtarget::X86Subtarget(const std::string &TT, const std::string &CPU, + const std::string &FS, bool is64Bit, unsigned StackAlignOverride) : PICStyle(PICStyles::None) , X86SSELevel(NoMMXSSE) @@ -308,10 +309,12 @@ X86Subtarget::X86Subtarget(const std::string &TT, const std::string &FS, , Is64Bit(is64Bit) { // Determine default and user specified characteristics - if (!FS.empty()) { + if (!CPU.empty() || !FS.empty()) { // If feature string is not empty, parse features string. - std::string CPU = sys::getHostCPUName(); - ParseSubtargetFeatures(FS, CPU); + std::string CPUName = CPU; + if (CPUName.empty()) + CPUName = sys::getHostCPUName(); + ParseSubtargetFeatures(FS, CPUName); // All X86-64 CPUs also have SSE2, however user might request no SSE via // -mattr, so don't force SSELevel here. if (HasAVX) diff --git a/lib/Target/X86/X86Subtarget.h b/lib/Target/X86/X86Subtarget.h index 49bf74b..80a4103 100644 --- a/lib/Target/X86/X86Subtarget.h +++ b/lib/Target/X86/X86Subtarget.h @@ -117,7 +117,8 @@ public: /// This constructor initializes the data members to match that /// of the specified triple. /// - X86Subtarget(const std::string &TT, const std::string &FS, bool is64Bit, + X86Subtarget(const std::string &TT, const std::string &CPU, + const std::string &FS, bool is64Bit, unsigned StackAlignOverride); /// getStackAlignment - Returns the minimum alignment known to hold of the @@ -131,8 +132,7 @@ public: /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. - std::string ParseSubtargetFeatures(const std::string &FS, - const std::string &CPU); + void ParseSubtargetFeatures(const std::string &FS, const std::string &CPU); /// AutoDetectSubtargetFeatures - Auto-detect CPU features using CPUID /// instruction. diff --git a/lib/Target/X86/X86TargetMachine.cpp b/lib/Target/X86/X86TargetMachine.cpp index c10bf1c..1b6fa30 100644 --- a/lib/Target/X86/X86TargetMachine.cpp +++ b/lib/Target/X86/X86TargetMachine.cpp @@ -87,8 +87,9 @@ extern "C" void LLVMInitializeX86Target() { X86_32TargetMachine::X86_32TargetMachine(const Target &T, const std::string &TT, + const std::string &CPU, const std::string &FS) - : X86TargetMachine(T, TT, FS, false), + : X86TargetMachine(T, TT, CPU, FS, false), DataLayout(getSubtargetImpl()->isTargetDarwin() ? "e-p:32:32-f64:32:64-i64:32:64-f80:128:128-f128:128:128-n8:16:32" : (getSubtargetImpl()->isTargetCygMing() || @@ -103,8 +104,9 @@ X86_32TargetMachine::X86_32TargetMachine(const Target &T, const std::string &TT, X86_64TargetMachine::X86_64TargetMachine(const Target &T, const std::string &TT, + const std::string &CPU, const std::string &FS) - : X86TargetMachine(T, TT, FS, true), + : X86TargetMachine(T, TT, CPU, FS, true), DataLayout("e-p:64:64-s:64-f64:64:64-i64:64:64-f80:128:128-f128:128:128-n8:16:32:64"), InstrInfo(*this), TSInfo(*this), @@ -115,9 +117,10 @@ X86_64TargetMachine::X86_64TargetMachine(const Target &T, const std::string &TT, /// X86TargetMachine ctor - Create an X86 target. /// X86TargetMachine::X86TargetMachine(const Target &T, const std::string &TT, + const std::string &CPU, const std::string &FS, bool is64Bit) : LLVMTargetMachine(T, TT), - Subtarget(TT, FS, is64Bit, StackAlignmentOverride), + Subtarget(TT, CPU, FS, is64Bit, StackAlignmentOverride), FrameLowering(*this, Subtarget), ELFWriterInfo(is64Bit, true) { DefRelocModel = getRelocationModel(); diff --git a/lib/Target/X86/X86TargetMachine.h b/lib/Target/X86/X86TargetMachine.h index 5973922..885334a 100644 --- a/lib/Target/X86/X86TargetMachine.h +++ b/lib/Target/X86/X86TargetMachine.h @@ -43,7 +43,8 @@ private: public: X86TargetMachine(const Target &T, const std::string &TT, - const std::string &FS, bool is64Bit); + const std::string &CPU, const std::string &FS, + bool is64Bit); virtual const X86InstrInfo *getInstrInfo() const { llvm_unreachable("getInstrInfo not implemented"); @@ -87,7 +88,7 @@ class X86_32TargetMachine : public X86TargetMachine { X86JITInfo JITInfo; public: X86_32TargetMachine(const Target &T, const std::string &M, - const std::string &FS); + const std::string &CPU, const std::string &FS); virtual const TargetData *getTargetData() const { return &DataLayout; } virtual const X86TargetLowering *getTargetLowering() const { return &TLInfo; @@ -113,7 +114,7 @@ class X86_64TargetMachine : public X86TargetMachine { X86JITInfo JITInfo; public: X86_64TargetMachine(const Target &T, const std::string &TT, - const std::string &FS); + const std::string &CPU, const std::string &FS); virtual const TargetData *getTargetData() const { return &DataLayout; } virtual const X86TargetLowering *getTargetLowering() const { return &TLInfo; diff --git a/lib/Target/XCore/XCoreSubtarget.cpp b/lib/Target/XCore/XCoreSubtarget.cpp index 78a6fa5..0447d2e 100644 --- a/lib/Target/XCore/XCoreSubtarget.cpp +++ b/lib/Target/XCore/XCoreSubtarget.cpp @@ -15,6 +15,7 @@ #include "XCore.h" using namespace llvm; -XCoreSubtarget::XCoreSubtarget(const std::string &TT, const std::string &FS) +XCoreSubtarget::XCoreSubtarget(const std::string &TT, + const std::string &CPU, const std::string &FS) { } diff --git a/lib/Target/XCore/XCoreSubtarget.h b/lib/Target/XCore/XCoreSubtarget.h index f8be3ec..ee40d36 100644 --- a/lib/Target/XCore/XCoreSubtarget.h +++ b/lib/Target/XCore/XCoreSubtarget.h @@ -27,12 +27,12 @@ public: /// This constructor initializes the data members to match that /// of the specified triple. /// - XCoreSubtarget(const std::string &TT, const std::string &FS); + XCoreSubtarget(const std::string &TT, const std::string &CPU, + const std::string &FS); /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. - std::string ParseSubtargetFeatures(const std::string &FS, - const std::string &CPU); + void ParseSubtargetFeatures(const std::string &FS, const std::string &CPU); }; } // End llvm namespace diff --git a/lib/Target/XCore/XCoreTargetMachine.cpp b/lib/Target/XCore/XCoreTargetMachine.cpp index 30da2c8..542038b 100644 --- a/lib/Target/XCore/XCoreTargetMachine.cpp +++ b/lib/Target/XCore/XCoreTargetMachine.cpp @@ -21,9 +21,10 @@ using namespace llvm; /// XCoreTargetMachine ctor - Create an ILP32 architecture model /// XCoreTargetMachine::XCoreTargetMachine(const Target &T, const std::string &TT, + const std::string &CPU, const std::string &FS) : LLVMTargetMachine(T, TT), - Subtarget(TT, FS), + Subtarget(TT, CPU, FS), DataLayout("e-p:32:32:32-a0:0:32-f32:32:32-f64:32:32-i1:8:32-i8:8:32-" "i16:16:32-i32:32:32-i64:32:32-n32"), InstrInfo(), diff --git a/lib/Target/XCore/XCoreTargetMachine.h b/lib/Target/XCore/XCoreTargetMachine.h index 24daadc..6235ac3 100644 --- a/lib/Target/XCore/XCoreTargetMachine.h +++ b/lib/Target/XCore/XCoreTargetMachine.h @@ -33,7 +33,7 @@ class XCoreTargetMachine : public LLVMTargetMachine { XCoreSelectionDAGInfo TSInfo; public: XCoreTargetMachine(const Target &T, const std::string &TT, - const std::string &FS); + const std::string &CPU, const std::string &FS); virtual const XCoreInstrInfo *getInstrInfo() const { return &InstrInfo; } virtual const XCoreFrameLowering *getFrameLowering() const { diff --git a/tools/llc/llc.cpp b/tools/llc/llc.cpp index e89b4d8..a2e508d 100644 --- a/tools/llc/llc.cpp +++ b/tools/llc/llc.cpp @@ -261,16 +261,16 @@ int main(int argc, char **argv) { // Package up features to be passed to target/subtarget std::string FeaturesStr; - if (MCPU.size() || MAttrs.size()) { + if (MAttrs.size()) { SubtargetFeatures Features; - Features.setCPU(MCPU); for (unsigned i = 0; i != MAttrs.size(); ++i) Features.AddFeature(MAttrs[i]); FeaturesStr = Features.getString(); } std::auto_ptr - target(TheTarget->createTargetMachine(TheTriple.getTriple(), FeaturesStr)); + target(TheTarget->createTargetMachine(TheTriple.getTriple(), MCPU, + FeaturesStr)); assert(target.get() && "Could not allocate target machine!"); TargetMachine &Target = *target.get(); diff --git a/tools/llvm-mc/llvm-mc.cpp b/tools/llvm-mc/llvm-mc.cpp index e224459..b1d9a60 100644 --- a/tools/llvm-mc/llvm-mc.cpp +++ b/tools/llvm-mc/llvm-mc.cpp @@ -309,17 +309,13 @@ static int AssembleInput(const char *ProgName) { // Package up features to be passed to target/subtarget std::string FeaturesStr; - if (MCPU.size()) { - SubtargetFeatures Features; - Features.setCPU(MCPU); - FeaturesStr = Features.getString(); - } // FIXME: We shouldn't need to do this (and link in codegen). // When we split this out, we should do it in a way that makes // it straightforward to switch subtargets on the fly (.e.g, // the .cpu and .code16 directives). OwningPtr TM(TheTarget->createTargetMachine(TripleName, + MCPU, FeaturesStr)); if (!TM) { @@ -415,17 +411,13 @@ static int DisassembleInput(const char *ProgName, bool Enhanced) { } else { // Package up features to be passed to target/subtarget std::string FeaturesStr; - if (MCPU.size()) { - SubtargetFeatures Features; - Features.setCPU(MCPU); - FeaturesStr = Features.getString(); - } // FIXME: We shouldn't need to do this (and link in codegen). // When we split this out, we should do it in a way that makes // it straightforward to switch subtargets on the fly (.e.g, // the .cpu and .code16 directives). OwningPtr TM(TheTarget->createTargetMachine(TripleName, + MCPU, FeaturesStr)); if (!TM) { diff --git a/tools/llvm-objdump/llvm-objdump.cpp b/tools/llvm-objdump/llvm-objdump.cpp index c971e49..a125c91 100644 --- a/tools/llvm-objdump/llvm-objdump.cpp +++ b/tools/llvm-objdump/llvm-objdump.cpp @@ -201,7 +201,8 @@ static void DisassembleInput(const StringRef &Filename) { // it straightforward to switch subtargets on the fly (.e.g, // the .cpu and .code16 directives). std::string FeaturesStr; - OwningPtr TM(TheTarget->createTargetMachine(TripleName, + std::string CPU; + OwningPtr TM(TheTarget->createTargetMachine(TripleName, CPU, FeaturesStr)); if (!TM) { errs() << "error: could not create target for triple " << TripleName << "\n"; diff --git a/tools/lto/LTOCodeGenerator.cpp b/tools/lto/LTOCodeGenerator.cpp index f175255..630a995 100644 --- a/tools/lto/LTOCodeGenerator.cpp +++ b/tools/lto/LTOCodeGenerator.cpp @@ -262,9 +262,9 @@ bool LTOCodeGenerator::determineTarget(std::string& errMsg) // construct LTModule, hand over ownership of module and target SubtargetFeatures Features; - Features.getDefaultSubtargetFeatures(_mCpu, llvm::Triple(Triple)); + Features.getDefaultSubtargetFeatures(llvm::Triple(Triple)); std::string FeatureStr = Features.getString(); - _target = march->createTargetMachine(Triple, FeatureStr); + _target = march->createTargetMachine(Triple, _mCpu, FeatureStr); } return false; } diff --git a/tools/lto/LTOModule.cpp b/tools/lto/LTOModule.cpp index 814d80b..f8b42f1 100644 --- a/tools/lto/LTOModule.cpp +++ b/tools/lto/LTOModule.cpp @@ -157,9 +157,10 @@ LTOModule *LTOModule::makeLTOModule(MemoryBuffer *buffer, // construct LTOModule, hand over ownership of module and target SubtargetFeatures Features; - Features.getDefaultSubtargetFeatures("" /* cpu */, llvm::Triple(Triple)); + Features.getDefaultSubtargetFeatures(llvm::Triple(Triple)); std::string FeatureStr = Features.getString(); - TargetMachine *target = march->createTargetMachine(Triple, FeatureStr); + std::string CPU; + TargetMachine *target = march->createTargetMachine(Triple, CPU, FeatureStr); LTOModule *Ret = new LTOModule(m.take(), target); bool Err = Ret->ParseSymbols(); if (Err) { diff --git a/utils/TableGen/SubtargetEmitter.cpp b/utils/TableGen/SubtargetEmitter.cpp index 6899cb1..c823cb1 100644 --- a/utils/TableGen/SubtargetEmitter.cpp +++ b/utils/TableGen/SubtargetEmitter.cpp @@ -606,15 +606,15 @@ void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS) { OS << "// ParseSubtargetFeatures - Parses features string setting specified\n" << "// subtarget options.\n" - << "std::string llvm::"; + << "void llvm::"; OS << Target; OS << "Subtarget::ParseSubtargetFeatures(const std::string &FS,\n" << " const std::string &CPU) {\n" << " DEBUG(dbgs() << \"\\nFeatures:\" << FS);\n" << " DEBUG(dbgs() << \"\\nCPU:\" << CPU);\n" << " SubtargetFeatures Features(FS);\n" - << " Features.setCPUIfNone(CPU);\n" - << " uint64_t Bits = Features.getBits(SubTypeKV, SubTypeKVSize,\n" + << " uint64_t Bits = Features.getFeatureBits(CPU, " + << "SubTypeKV, SubTypeKVSize,\n" << " FeatureKV, FeatureKVSize);\n"; for (unsigned i = 0; i < Features.size(); i++) { @@ -635,13 +635,13 @@ void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS) { if (HasItineraries) { OS << "\n" << " InstrItinerary *Itinerary = (InstrItinerary *)" - << "Features.getInfo(ProcItinKV, ProcItinKVSize);\n" + << "Features.getItinerary(CPU, " + << "ProcItinKV, ProcItinKVSize);\n" << " InstrItins = InstrItineraryData(Stages, OperandCycles, " << "ForwardingPathes, Itinerary);\n"; } - OS << " return Features.getCPU();\n" - << "}\n"; + OS << "}\n"; } // -- cgit v1.1 From 4cc446bc400b2ff58af81c91f5e145b81d6beb26 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Thu, 30 Jun 2011 02:12:44 +0000 Subject: Fix ARMSubtarget feature parsing. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134129 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMSubtarget.cpp | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/lib/Target/ARM/ARMSubtarget.cpp b/lib/Target/ARM/ARMSubtarget.cpp index cf67497..694b313 100644 --- a/lib/Target/ARM/ARMSubtarget.cpp +++ b/lib/Target/ARM/ARMSubtarget.cpp @@ -120,17 +120,14 @@ ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &CPU, if (TT.find("eabi") != std::string::npos) TargetABI = ARM_ABI_AAPCS; - // Parse features string. If the first entry in FS (the CPU) is missing, - // insert the architecture feature derived from the target triple. This is - // important for setting features that are implied based on the architecture - // version. - std::string FSWithArch; - if (FS.empty()) - FSWithArch = std::string(ARMArchFeature); - else if (FS.find(',') == 0) - FSWithArch = std::string(ARMArchFeature) + FS; - else + // Insert the architecture feature derived from the target triple into the + // feature string. This is important for setting features that are implied + // based on the architecture version. + std::string FSWithArch = std::string(ARMArchFeature); + if (FSWithArch.empty()) FSWithArch = FS; + else if (!FS.empty()) + FSWithArch = FSWithArch + "," + FS; ParseSubtargetFeatures(FSWithArch, CPUString); // After parsing Itineraries, set ItinData.IssueWidth. -- cgit v1.1 From 41ca4b7b62fc40b3207eff0526171653605efa19 Mon Sep 17 00:00:00 2001 From: Jim Grosbach Date: Thu, 30 Jun 2011 02:22:49 +0000 Subject: Size reducing SP adjusting t2ADDri needs to check predication. tADDrSPi is not predicable, so we can't size-reduce a t2ADDri to it if the predicate is anything other than "always." git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134130 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/Thumb2SizeReduction.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/Target/ARM/Thumb2SizeReduction.cpp b/lib/Target/ARM/Thumb2SizeReduction.cpp index 65846b2..cb44f8e 100644 --- a/lib/Target/ARM/Thumb2SizeReduction.cpp +++ b/lib/Target/ARM/Thumb2SizeReduction.cpp @@ -491,11 +491,14 @@ Thumb2SizeReduce::ReduceSpecial(MachineBasicBlock &MBB, MachineInstr *MI, // Try to reduce to tADDrSPi. unsigned Imm = MI->getOperand(2).getImm(); // The immediate must be in range, the destination register must be a low - // reg, and the condition flags must not be being set. + // reg, the predicate must be "always" and the condition flags must not + // be being set. if (Imm & 3 || Imm > 1024) return false; if (!isARMLowRegister(MI->getOperand(0).getReg())) return false; + if (MI->getOperand(3).getImm() != ARMCC::AL) + return false; const MCInstrDesc &MCID = MI->getDesc(); if (MCID.hasOptionalDef() && MI->getOperand(MCID.getNumOperands()-1).getReg() == ARM::CPSR) -- cgit v1.1 From dafc17e2c2a13697f7f80f5965104290e2912464 Mon Sep 17 00:00:00 2001 From: Jim Grosbach Date: Thu, 30 Jun 2011 02:23:05 +0000 Subject: Kill dead code. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134131 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/Thumb2InstrInfo.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/Target/ARM/Thumb2InstrInfo.cpp b/lib/Target/ARM/Thumb2InstrInfo.cpp index 0e08ea2..b1991f1 100644 --- a/lib/Target/ARM/Thumb2InstrInfo.cpp +++ b/lib/Target/ARM/Thumb2InstrInfo.cpp @@ -419,7 +419,6 @@ bool llvm::rewriteT2FrameIndex(MachineInstr &MI, unsigned FrameRegIdx, return true; } - bool isSP = FrameReg == ARM::SP; bool HasCCOut = Opcode != ARM::t2ADDri12; if (Offset < 0) { -- cgit v1.1 From eb7fe5df1b6318ae793bf32f9988c4cbc3c5ad74 Mon Sep 17 00:00:00 2001 From: Duncan Sands Date: Thu, 30 Jun 2011 06:37:07 +0000 Subject: The enum was moved to ISDOpcodes.h. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134134 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/ExtendingLLVM.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/ExtendingLLVM.html b/docs/ExtendingLLVM.html index b720911..795e211 100644 --- a/docs/ExtendingLLVM.html +++ b/docs/ExtendingLLVM.html @@ -146,7 +146,7 @@ cases, new nodes have been added to allow many targets to perform a common task complicated behavior in a single node (rotate).

    -
  1. include/llvm/CodeGen/SelectionDAGNodes.h: +
  2. include/llvm/CodeGen/ISDOpcodes.h: Add an enum value for the new SelectionDAG node.
  3. lib/CodeGen/SelectionDAG/SelectionDAG.cpp: Add code to print the node to getOperationName. If your new node -- cgit v1.1 From ef17e01725740a91bd12723520f6edb2f12526d2 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Thu, 30 Jun 2011 13:17:24 +0000 Subject: Remove dead code. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134148 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/RegisterCoalescer.h | 88 ----------------------------------------- 1 file changed, 88 deletions(-) diff --git a/lib/CodeGen/RegisterCoalescer.h b/lib/CodeGen/RegisterCoalescer.h index f06675a..4131d91 100644 --- a/lib/CodeGen/RegisterCoalescer.h +++ b/lib/CodeGen/RegisterCoalescer.h @@ -160,94 +160,6 @@ namespace llvm { virtual void print(raw_ostream &O, const Module* = 0) const; }; - /// An abstract interface for register allocators to interact with - /// coalescers - /// - /// Example: - /// - /// This is simply an example of how to use the RegallocQuery - /// interface. It is not meant to be used in production. - /// - /// class LinearScanRegallocQuery : public RegallocQuery { - /// private: - /// const LiveIntervals \&li; - /// - /// public: - /// LinearScanRegallocQuery(LiveIntervals &intervals) - /// : li(intervals) {} - /// - /// /// This is pretty slow and conservative, but since linear scan - /// /// allocation doesn't pre-compute interference information it's - /// /// the best we can do. Coalescers are always free to ignore this - /// /// and implement their own discovery strategy. See - /// /// RegisterCoalescer for an example. - /// void getInterferences(IntervalSet &interferences, - /// const LiveInterval &a) const { - /// for(LiveIntervals::const_iterator iv = li.begin(), - /// ivend = li.end(); - /// iv != ivend; - /// ++iv) { - /// if (interfere(a, iv->second)) { - /// interferences.insert(&iv->second); - /// } - /// } - /// } - /// - /// /// This is *really* slow and stupid. See above. - /// int getNumberOfInterferences(const LiveInterval &a) const { - /// IntervalSet intervals; - /// getInterferences(intervals, a); - /// return intervals.size(); - /// } - /// }; - /// - /// In the allocator: - /// - /// RegisterCoalescer &coalescer = getAnalysis(); - /// - /// // We don't reset the coalescer so if it's already been run this - /// // takes almost no time. - /// LinearScanRegallocQuery ifd(*li_); - /// - class RegallocQuery { - public: - typedef SmallPtrSet IntervalSet; - - virtual ~RegallocQuery() {} - - /// Return whether two live ranges interfere. - virtual bool interfere(const LiveInterval &a, - const LiveInterval &b) const { - // A naive test - return a.overlaps(b); - } - - /// Return the set of intervals that interfere with this one. - virtual void getInterferences(IntervalSet &interferences, - const LiveInterval &a) const = 0; - - /// This can often be cheaper than actually returning the - /// interferences. - virtual int getNumberOfInterferences(const LiveInterval &a) const = 0; - - /// Make any data structure updates necessary to reflect - /// coalescing or other modifications. - virtual void updateDataForMerge(const LiveInterval &a, - const LiveInterval &b, - const MachineInstr ©) {} - - /// Allow the register allocator to communicate when it doesn't - /// want a copy coalesced. This may be due to assumptions made by - /// the allocator about various invariants and so this question is - /// a matter of legality, not performance. Performance decisions - /// about which copies to coalesce should be made by the - /// coalescer. - virtual bool isLegalToCoalesce(const MachineInstr &inst) const { - return true; - } - }; - - /// CoalescerPair - A helper class for register coalescers. When deciding if /// two registers can be coalesced, CoalescerPair can determine if a copy /// instruction would become an identity copy after coalescing. -- cgit v1.1 From 4629d505011d6d88ce181985005761df0dd3cbef Mon Sep 17 00:00:00 2001 From: Jim Grosbach Date: Thu, 30 Jun 2011 17:34:04 +0000 Subject: Pseudo-ize the Thumb tPOP_RET instruction. It's just a tPOP instruction with additional code-gen properties, so it doesn't need encoding information. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134172 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMAsmPrinter.cpp | 8 ++++++++ lib/Target/ARM/ARMInstrThumb.td | 11 ++--------- utils/TableGen/ARMDecoderEmitter.cpp | 4 ++-- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/lib/Target/ARM/ARMAsmPrinter.cpp b/lib/Target/ARM/ARMAsmPrinter.cpp index 4059560..1975c6d 100644 --- a/lib/Target/ARM/ARMAsmPrinter.cpp +++ b/lib/Target/ARM/ARMAsmPrinter.cpp @@ -1096,6 +1096,14 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { OutStreamer.EmitInstruction(TmpInst); return; } + case ARM::tPOP_RET: { + // As above for LDMIA_RET. Map to the tPOP instruction. + MCInst TmpInst; + LowerARMMachineInstrToMCInst(MI, TmpInst, *this); + TmpInst.setOpcode(ARM::tPOP); + OutStreamer.EmitInstruction(TmpInst); + return; + } case ARM::t2MOVi32imm: assert(0 && "Should be lowered by thumb2it pass"); case ARM::DBG_VALUE: { diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td index 735f3e9..bb261ec 100644 --- a/lib/Target/ARM/ARMInstrThumb.td +++ b/lib/Target/ARM/ARMInstrThumb.td @@ -408,15 +408,8 @@ let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in { // FIXME: remove when we have a way to marking a MI with these properties. let isReturn = 1, isTerminator = 1, isBarrier = 1, mayLoad = 1, hasExtraDefRegAllocReq = 1 in -def tPOP_RET : T1I<(outs), (ins pred:$p, reglist:$regs, variable_ops), - IIC_iPop_Br, - "pop${p}\t$regs", []>, - T1Misc<{1,1,0,?,?,?,?}> { - // A8.6.121 - bits<16> regs; - let Inst{8} = regs{15}; // registers = P:'0000000':register_list - let Inst{7-0} = regs{7-0}; -} +def tPOP_RET : tPseudoInst<(outs), (ins pred:$p, reglist:$regs, variable_ops), + Size4Bytes, IIC_iPop_Br, []>; // All calls clobber the non-callee saved registers. SP is marked as a use to // prevent stack-pointer assignments that appear immediately before calls from diff --git a/utils/TableGen/ARMDecoderEmitter.cpp b/utils/TableGen/ARMDecoderEmitter.cpp index 4ccab9b..b3aac98 100644 --- a/utils/TableGen/ARMDecoderEmitter.cpp +++ b/utils/TableGen/ARMDecoderEmitter.cpp @@ -1656,13 +1656,13 @@ ARMDEBackend::populateInstruction(const CodeGenInstruction &CGI, // Resolve conflicts: // // tBfar conflicts with tBLr9 - // tPOP_RET/t2LDMIA_RET conflict with tPOP/t2LDM (ditto) + // t2LDMIA_RET conflict with t2LDM (ditto) // tMOVCCi conflicts with tMOVi8 // tMOVCCr conflicts with tMOVgpr2gpr // tLDRcp conflicts with tLDRspi // t2MOVCCi16 conflicts with tMOVi16 if (Name == "tBfar" || - Name == "tPOP_RET" || Name == "t2LDMIA_RET" || + Name == "t2LDMIA_RET" || Name == "tMOVCCi" || Name == "tMOVCCr" || Name == "tLDRcp" || Name == "t2MOVCCi16") -- cgit v1.1 From 16f9924000a8d513353cd5c69d1d6307016fe280 Mon Sep 17 00:00:00 2001 From: Jim Grosbach Date: Thu, 30 Jun 2011 18:25:42 +0000 Subject: Pseudo-ize the t2LDMIA_RET instruction. It's just a t2LDMIA_UPD instruction with extra codegen properties, so it doesn't need the encoding information. As a side-benefit, we now correctly recognize for instruction printing as a 'pop' instruction. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134173 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMAsmPrinter.cpp | 8 ++++++++ lib/Target/ARM/ARMInstrThumb2.td | 23 ++++------------------- test/CodeGen/Thumb2/2009-10-15-ITBlockBranch.ll | 2 +- 3 files changed, 13 insertions(+), 20 deletions(-) diff --git a/lib/Target/ARM/ARMAsmPrinter.cpp b/lib/Target/ARM/ARMAsmPrinter.cpp index 1975c6d..300cff5 100644 --- a/lib/Target/ARM/ARMAsmPrinter.cpp +++ b/lib/Target/ARM/ARMAsmPrinter.cpp @@ -1096,6 +1096,14 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { OutStreamer.EmitInstruction(TmpInst); return; } + case ARM::t2LDMIA_RET: { + // As above for LDMIA_RET. Map to the tPOP instruction. + MCInst TmpInst; + LowerARMMachineInstrToMCInst(MI, TmpInst, *this); + TmpInst.setOpcode(ARM::t2LDMIA_UPD); + OutStreamer.EmitInstruction(TmpInst); + return; + } case ARM::tPOP_RET: { // As above for LDMIA_RET. Map to the tPOP instruction. MCInst TmpInst; diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td index 95475bb..ffa2d89 100644 --- a/lib/Target/ARM/ARMInstrThumb2.td +++ b/lib/Target/ARM/ARMInstrThumb2.td @@ -2962,28 +2962,13 @@ let Defs = // // FIXME: remove when we have a way to marking a MI with these properties. -// FIXME: $dst1 should be a def. But the extra ops must be in the end of the -// operand list. // FIXME: Should pc be an implicit operand like PICADD, etc? let isReturn = 1, isTerminator = 1, isBarrier = 1, mayLoad = 1, hasExtraDefRegAllocReq = 1, isCodeGenOnly = 1 in -def t2LDMIA_RET: T2XIt<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, - reglist:$regs, variable_ops), - IIC_iLoad_mBr, - "ldmia${p}.w\t$Rn!, $regs", - "$Rn = $wb", []> { - bits<4> Rn; - bits<16> regs; - - let Inst{31-27} = 0b11101; - let Inst{26-25} = 0b00; - let Inst{24-23} = 0b01; // Increment After - let Inst{22} = 0; - let Inst{21} = 1; // Writeback - let Inst{20} = 1; - let Inst{19-16} = Rn; - let Inst{15-0} = regs; -} +def t2LDMIA_RET: t2PseudoInst<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, + reglist:$regs, variable_ops), + Size4Bytes, IIC_iLoad_mBr, []>, + RegConstraint<"$Rn = $wb">; let isBranch = 1, isTerminator = 1, isBarrier = 1 in { let isPredicable = 1 in diff --git a/test/CodeGen/Thumb2/2009-10-15-ITBlockBranch.ll b/test/CodeGen/Thumb2/2009-10-15-ITBlockBranch.ll index 9aee910..18c2e0b 100644 --- a/test/CodeGen/Thumb2/2009-10-15-ITBlockBranch.ll +++ b/test/CodeGen/Thumb2/2009-10-15-ITBlockBranch.ll @@ -13,7 +13,7 @@ define weak arm_aapcs_vfpcc i32 @_ZNKSs7compareERKSs(%"struct.std::basic_string< ; CHECK: _ZNKSs7compareERKSs: ; CHECK: it eq ; CHECK-NEXT: subeq{{(.w)?}} r0, r{{[0-9]+}}, r{{[0-9]+}} -; CHECK-NEXT: ldmia.w sp!, +; CHECK-NEXT: pop.w entry: %0 = tail call arm_aapcs_vfpcc i32 @_ZNKSs4sizeEv(%"struct.std::basic_string,std::allocator >"* %this) ; [#uses=3] %1 = tail call arm_aapcs_vfpcc i32 @_ZNKSs4sizeEv(%"struct.std::basic_string,std::allocator >"* %__str) ; [#uses=3] -- cgit v1.1 From 6e0ce24e0ca8b0dc05872b9b4cec3a18972bee40 Mon Sep 17 00:00:00 2001 From: Andrew Trick Date: Thu, 30 Jun 2011 19:02:17 +0000 Subject: indvars -disable-iv-rewrite: handle cloning binary operators that cannot overflow. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134177 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Scalar/IndVarSimplify.cpp | 10 ++++-- test/Transforms/IndVarSimplify/no-iv-rewrite.ll | 42 ++++++++++++++++++++++--- 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/lib/Transforms/Scalar/IndVarSimplify.cpp b/lib/Transforms/Scalar/IndVarSimplify.cpp index 00f8831..77642e5 100644 --- a/lib/Transforms/Scalar/IndVarSimplify.cpp +++ b/lib/Transforms/Scalar/IndVarSimplify.cpp @@ -659,9 +659,11 @@ Instruction *WidenIV::CloneIVUser(Instruction *NarrowUse, LHS, RHS, NarrowBO->getName()); Builder.Insert(WideBO); - if (NarrowBO->hasNoUnsignedWrap()) WideBO->setHasNoUnsignedWrap(); - if (NarrowBO->hasNoSignedWrap()) WideBO->setHasNoSignedWrap(); - + if (const OverflowingBinaryOperator *OBO = + dyn_cast(NarrowBO)) { + if (OBO->hasNoUnsignedWrap()) WideBO->setHasNoUnsignedWrap(); + if (OBO->hasNoSignedWrap()) WideBO->setHasNoSignedWrap(); + } return WideBO; } llvm_unreachable(0); @@ -1121,6 +1123,8 @@ void IndVarSimplify::SimplifyIVUsersNoRewrite(Loop *L, SCEVExpander &Rewriter) { while (!SimpleIVUsers.empty()) { Instruction *UseInst, *Operand; tie(UseInst, Operand) = SimpleIVUsers.pop_back_val(); + // Bypass back edges to avoid extra work. + if (UseInst == CurrIV) continue; if (EliminateIVUser(UseInst, Operand)) { pushIVUsers(Operand, Simplified, SimpleIVUsers); diff --git a/test/Transforms/IndVarSimplify/no-iv-rewrite.ll b/test/Transforms/IndVarSimplify/no-iv-rewrite.ll index 0187170..f38b54e 100644 --- a/test/Transforms/IndVarSimplify/no-iv-rewrite.ll +++ b/test/Transforms/IndVarSimplify/no-iv-rewrite.ll @@ -160,6 +160,8 @@ define void @maxvisitor(i32 %limit, i32* %base) nounwind { entry: br label %loop +; Test inserting a truncate at a phi use. +; ; CHECK: loop: ; CHECK: phi i64 ; CHECK: trunc @@ -189,14 +191,17 @@ exit: ret void } -; CHECK: loop: -; CHECK: phi i32 -; CHECK-NOT: phi -; CHECK: exit: define void @identityphi(i32 %limit) nounwind { entry: br label %loop +; Test an edge case of removing an identity phi that directly feeds +; back to the loop iv. +; +; CHECK: loop: +; CHECK: phi i32 +; CHECK-NOT: phi +; CHECK: exit: loop: %iv = phi i32 [ 0, %entry], [ %iv.next, %control ] br i1 undef, label %if.then, label %control @@ -212,3 +217,32 @@ control: exit: ret void } + +define i64 @cloneOr(i32 %limit, i64* %base) nounwind { +entry: + ; ensure that the loop can't overflow + %halfLim = ashr i32 %limit, 2 + br label %loop + +; Test cloning an or, which is not an OverflowBinaryOperator. +; +; CHECK: loop: +; CHECK: phi i64 +; CHECK-NOT: sext +; CHECK: or i64 +; CHECK: exit: +loop: + %iv = phi i32 [ 0, %entry], [ %iv.next, %loop ] + %t1 = sext i32 %iv to i64 + %adr = getelementptr i64* %base, i64 %t1 + %val = load i64* %adr + %t2 = or i32 %iv, 1 + %t3 = sext i32 %t2 to i64 + %iv.next = add i32 %iv, 2 + %cmp = icmp slt i32 %iv.next, %halfLim + br i1 %cmp, label %loop, label %exit + +exit: + %result = and i64 %val, %t3 + ret i64 %result +} -- cgit v1.1 From ff97eb0cf4394090570feaa327d1237ba4b935e2 Mon Sep 17 00:00:00 2001 From: Jim Grosbach Date: Thu, 30 Jun 2011 19:38:01 +0000 Subject: Pseudo-ize the Thumb tTPsoft instruction. It's just a call to a special helper function. Get rid of the T2 variant entirely, as it's identical to the Thumb1 version. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134178 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMExpandPseudoInsts.cpp | 3 ++- lib/Target/ARM/ARMInstrThumb.td | 12 +++++------- lib/Target/ARM/ARMInstrThumb2.td | 16 ---------------- utils/TableGen/ARMDecoderEmitter.cpp | 4 ---- 4 files changed, 7 insertions(+), 28 deletions(-) diff --git a/lib/Target/ARM/ARMExpandPseudoInsts.cpp b/lib/Target/ARM/ARMExpandPseudoInsts.cpp index 71b33d3..53a5f7d 100644 --- a/lib/Target/ARM/ARMExpandPseudoInsts.cpp +++ b/lib/Target/ARM/ARMExpandPseudoInsts.cpp @@ -856,10 +856,11 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB, MI.eraseFromParent(); return true; } + case ARM::tTPsoft: case ARM::TPsoft: { MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(), - TII->get(ARM::BL)) + TII->get(Opcode == ARM::tTPsoft ? ARM::tBL : ARM::BL)) .addExternalSymbol("__aeabi_read_tp", 0); MIB->setMemRefs(MI.memoperands_begin(), MI.memoperands_end()); diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td index bb261ec..10476335 100644 --- a/lib/Target/ARM/ARMInstrThumb.td +++ b/lib/Target/ARM/ARMInstrThumb.td @@ -1392,13 +1392,11 @@ def tCDP : T1Cop<(outs), (ins p_imm:$cop, i32imm:$opc1, // // __aeabi_read_tp preserves the registers r1-r3. -let isCall = 1, Defs = [R0, LR], Uses = [SP] in -def tTPsoft : TIx2<0b11110, 0b11, 1, (outs), (ins), IIC_Br, - "bl\t__aeabi_read_tp", - [(set R0, ARMthread_pointer)]> { - // Encoding is 0xf7fffffe. - let Inst = 0xf7fffffe; -} +// This is a pseudo inst so that we can get the encoding right, +// complete with fixup for the aeabi_read_tp function. +let isCall = 1, Defs = [R0, R12, LR, CPSR], Uses = [SP] in +def tTPsoft : tPseudoInst<(outs), (ins), Size4Bytes, IIC_Br, + [(set R0, ARMthread_pointer)]>; //===----------------------------------------------------------------------===// // SJLJ Exception handling intrinsics diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td index ffa2d89..d49b282 100644 --- a/lib/Target/ARM/ARMInstrThumb2.td +++ b/lib/Target/ARM/ARMInstrThumb2.td @@ -2909,22 +2909,6 @@ def t2CLREX : T2XI<(outs), (ins), NoItinerary, "clrex", } //===----------------------------------------------------------------------===// -// TLS Instructions -// - -// __aeabi_read_tp preserves the registers r1-r3. -let isCall = 1, - Defs = [R0, R12, LR, CPSR], Uses = [SP] in { - def t2TPsoft : T2XI<(outs), (ins), IIC_Br, - "bl\t__aeabi_read_tp", - [(set R0, ARMthread_pointer)]> { - let Inst{31-27} = 0b11110; - let Inst{15-14} = 0b11; - let Inst{12} = 1; - } -} - -//===----------------------------------------------------------------------===// // SJLJ Exception handling intrinsics // eh_sjlj_setjmp() is an instruction sequence to store the return // address and save #0 in R0 for the non-longjmp case. diff --git a/utils/TableGen/ARMDecoderEmitter.cpp b/utils/TableGen/ARMDecoderEmitter.cpp index b3aac98..a7cbbcd 100644 --- a/utils/TableGen/ARMDecoderEmitter.cpp +++ b/utils/TableGen/ARMDecoderEmitter.cpp @@ -1624,10 +1624,6 @@ ARMDEBackend::populateInstruction(const CodeGenInstruction &CGI, if (Name == "tBX_RET" || Name == "tBX_RET_vararg") return false; - // Ignore the TPsoft (TLS) instructions, which conflict with tBLr9. - if (Name == "tTPsoft" || Name == "t2TPsoft") - return false; - // Ignore tADR, prefer tADDrPCi. if (Name == "tADR") return false; -- cgit v1.1 From 77a2c372face15a302f4c9e5cb9acc035b8b3bd3 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Thu, 30 Jun 2011 20:14:24 +0000 Subject: Add r134057 back, but splice the predecessor after the successors phi nodes. Original message: Let simplify cfg simplify bb with only debug and lifetime intrinsics. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134182 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/BasicBlock.h | 6 ++++++ lib/Transforms/Utils/Local.cpp | 22 ++++++++++++---------- lib/Transforms/Utils/SimplifyCFG.cpp | 2 +- lib/VMCore/BasicBlock.cpp | 20 ++++++++++++++++++++ test/Transforms/SimplifyCFG/lifetime.ll | 29 +++++++++++++++++++++++++++++ 5 files changed, 68 insertions(+), 11 deletions(-) create mode 100644 test/Transforms/SimplifyCFG/lifetime.ll diff --git a/include/llvm/BasicBlock.h b/include/llvm/BasicBlock.h index b02c249..3b953c0 100644 --- a/include/llvm/BasicBlock.h +++ b/include/llvm/BasicBlock.h @@ -138,6 +138,12 @@ public: return const_cast(this)->getFirstNonPHIOrDbg(); } + // Same as above, but also skip lifetime intrinsics. + Instruction* getFirstNonPHIOrDbgOrLifetime(); + const Instruction* getFirstNonPHIOrDbgOrLifetime() const { + return const_cast(this)->getFirstNonPHIOrDbgOrLifetime(); + } + /// removeFromParent - This method unlinks 'this' from the containing /// function, but does not delete it. /// diff --git a/lib/Transforms/Utils/Local.cpp b/lib/Transforms/Utils/Local.cpp index b1dd733..0f6d9ae 100644 --- a/lib/Transforms/Utils/Local.cpp +++ b/lib/Transforms/Utils/Local.cpp @@ -536,9 +536,9 @@ static bool CanPropagatePredecessorsForPHIs(BasicBlock *BB, BasicBlock *Succ) { /// TryToSimplifyUncondBranchFromEmptyBlock - BB is known to contain an /// unconditional branch, and contains no instructions other than PHI nodes, -/// potential debug intrinsics and the branch. If possible, eliminate BB by -/// rewriting all the predecessors to branch to the successor block and return -/// true. If we can't transform, return false. +/// potential side-effect free intrinsics and the branch. If possible, +/// eliminate BB by rewriting all the predecessors to branch to the successor +/// block and return true. If we can't transform, return false. bool llvm::TryToSimplifyUncondBranchFromEmptyBlock(BasicBlock *BB) { assert(BB != &BB->getParent()->getEntryBlock() && "TryToSimplifyUncondBranchFromEmptyBlock called on entry block!"); @@ -613,13 +613,15 @@ bool llvm::TryToSimplifyUncondBranchFromEmptyBlock(BasicBlock *BB) { } } - while (PHINode *PN = dyn_cast(&BB->front())) { - if (Succ->getSinglePredecessor()) { - // BB is the only predecessor of Succ, so Succ will end up with exactly - // the same predecessors BB had. - Succ->getInstList().splice(Succ->begin(), - BB->getInstList(), BB->begin()); - } else { + if (Succ->getSinglePredecessor()) { + // BB is the only predecessor of Succ, so Succ will end up with exactly + // the same predecessors BB had. + + // Copy over any phi, debug or lifetime instruction. + BB->getTerminator()->eraseFromParent(); + Succ->getInstList().splice(Succ->getFirstNonPHI(), BB->getInstList()); + } else { + while (PHINode *PN = dyn_cast(&BB->front())) { // We explicitly check for such uses in CanPropagatePredecessorsForPHIs. assert(PN->use_empty() && "There shouldn't be any uses here!"); PN->eraseFromParent(); diff --git a/lib/Transforms/Utils/SimplifyCFG.cpp b/lib/Transforms/Utils/SimplifyCFG.cpp index 7b93b4a..49726d5 100644 --- a/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/lib/Transforms/Utils/SimplifyCFG.cpp @@ -2604,7 +2604,7 @@ bool SimplifyCFGOpt::SimplifyUncondBranch(BranchInst *BI, IRBuilder<> &Builder){ BasicBlock *BB = BI->getParent(); // If the Terminator is the only non-phi instruction, simplify the block. - BasicBlock::iterator I = BB->getFirstNonPHIOrDbg(); + BasicBlock::iterator I = BB->getFirstNonPHIOrDbgOrLifetime(); if (I->isTerminator() && BB != &BB->getParent()->getEntryBlock() && TryToSimplifyUncondBranchFromEmptyBlock(BB)) return true; diff --git a/lib/VMCore/BasicBlock.cpp b/lib/VMCore/BasicBlock.cpp index 7d47044..70265c8 100644 --- a/lib/VMCore/BasicBlock.cpp +++ b/lib/VMCore/BasicBlock.cpp @@ -147,6 +147,26 @@ Instruction* BasicBlock::getFirstNonPHIOrDbg() { return &*i; } +Instruction* BasicBlock::getFirstNonPHIOrDbgOrLifetime() { + // All valid basic blocks should have a terminator, + // which is not a PHINode. If we have an invalid basic + // block we'll get an assertion failure when dereferencing + // a past-the-end iterator. + BasicBlock::iterator i = begin(); + for (;; ++i) { + if (isa(i) || isa(i)) + continue; + + const IntrinsicInst *II = dyn_cast(i); + if (!II) + break; + if (II->getIntrinsicID() != Intrinsic::lifetime_start && + II->getIntrinsicID() != Intrinsic::lifetime_end) + break; + } + return &*i; +} + void BasicBlock::dropAllReferences() { for(iterator I = begin(), E = end(); I != E; ++I) I->dropAllReferences(); diff --git a/test/Transforms/SimplifyCFG/lifetime.ll b/test/Transforms/SimplifyCFG/lifetime.ll new file mode 100644 index 0000000..b794221 --- /dev/null +++ b/test/Transforms/SimplifyCFG/lifetime.ll @@ -0,0 +1,29 @@ +; RUN: opt < %s -simplifycfg -S | FileCheck %s + +; Test that a lifetime intrinsic doesn't prevent us from simplifying this. + +; CHECK: foo +; CHECK: entry: +; CHECK-NOT: bb0: +; CHECK-NOT: bb1: +; CHECK: ret +define void @foo(i1 %x) { +entry: + %a = alloca i8 + call void @llvm.lifetime.start(i64 -1, i8* %a) nounwind + br i1 %x, label %bb0, label %bb1 + +bb0: + call void @llvm.lifetime.end(i64 -1, i8* %a) nounwind + br label %bb1 + +bb1: + call void @f() + ret void +} + +declare void @f() + +declare void @llvm.lifetime.start(i64, i8* nocapture) nounwind + +declare void @llvm.lifetime.end(i64, i8* nocapture) nounwind -- cgit v1.1 From cfe5254cd34d9414d9f6b8aa02dc1239d71a703f Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Thu, 30 Jun 2011 21:15:52 +0000 Subject: Create a isFullCopy predicate. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134189 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CodeGen/MachineInstr.h | 3 +++ lib/CodeGen/InlineSpiller.cpp | 6 +----- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/include/llvm/CodeGen/MachineInstr.h b/include/llvm/CodeGen/MachineInstr.h index 07a14cf..788d149 100644 --- a/include/llvm/CodeGen/MachineInstr.h +++ b/include/llvm/CodeGen/MachineInstr.h @@ -278,6 +278,9 @@ public: bool isCopy() const { return getOpcode() == TargetOpcode::COPY; } + bool isFullCopy() const { + return isCopy() && !getOperand(0).getSubReg() && !getOperand(1).getSubReg(); + } /// isCopyLike - Return true if the instruction behaves like a copy. /// This does not include native copy instructions. diff --git a/lib/CodeGen/InlineSpiller.cpp b/lib/CodeGen/InlineSpiller.cpp index 19ae333..0273891 100644 --- a/lib/CodeGen/InlineSpiller.cpp +++ b/lib/CodeGen/InlineSpiller.cpp @@ -180,11 +180,7 @@ Spiller *createInlineSpiller(MachineFunctionPass &pass, /// isFullCopyOf - If MI is a COPY to or from Reg, return the other register, /// otherwise return 0. static unsigned isFullCopyOf(const MachineInstr *MI, unsigned Reg) { - if (!MI->isCopy()) - return 0; - if (MI->getOperand(0).getSubReg() != 0) - return 0; - if (MI->getOperand(1).getSubReg() != 0) + if (!MI->isFullCopy()) return 0; if (MI->getOperand(0).getReg() == Reg) return MI->getOperand(1).getReg(); -- cgit v1.1 From 3c163cfa60f9f196cd6a5a04e07baec3947fee0b Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Thu, 30 Jun 2011 21:25:51 +0000 Subject: Add comments to the ASM output to help understand the compact unwind and CIE tables. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134191 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/MC/MCDwarf.cpp | 67 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 61 insertions(+), 6 deletions(-) diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp index fd55cc0..82b7f8e 100644 --- a/lib/MC/MCDwarf.cpp +++ b/lib/MC/MCDwarf.cpp @@ -526,6 +526,40 @@ namespace { void EmitCFIInstruction(MCStreamer &Streamer, const MCCFIInstruction &Instr); }; + +} // end anonymous namespace + +static void EmitEncodingByte(MCStreamer &Streamer, unsigned Encoding, + StringRef Prefix) { + if (Streamer.isVerboseAsm()) { + const char *EncStr = 0; + switch (Encoding) { + default: EncStr = ""; + case dwarf::DW_EH_PE_absptr: EncStr = "absptr"; + case dwarf::DW_EH_PE_omit: EncStr = "omit"; + case dwarf::DW_EH_PE_pcrel: EncStr = "pcrel"; + case dwarf::DW_EH_PE_udata4: EncStr = "udata4"; + case dwarf::DW_EH_PE_udata8: EncStr = "udata8"; + case dwarf::DW_EH_PE_sdata4: EncStr = "sdata4"; + case dwarf::DW_EH_PE_sdata8: EncStr = "sdata8"; + case dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_udata4: EncStr = "pcrel udata4"; + case dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_sdata4: EncStr = "pcrel sdata4"; + case dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_udata8: EncStr = "pcrel udata8"; + case dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_sdata8: EncStr = "pcrel sdata8"; + case dwarf::DW_EH_PE_indirect |dwarf::DW_EH_PE_pcrel|dwarf::DW_EH_PE_udata4: + EncStr = "indirect pcrel udata4"; + case dwarf::DW_EH_PE_indirect |dwarf::DW_EH_PE_pcrel|dwarf::DW_EH_PE_sdata4: + EncStr = "indirect pcrel sdata4"; + case dwarf::DW_EH_PE_indirect |dwarf::DW_EH_PE_pcrel|dwarf::DW_EH_PE_udata8: + EncStr = "indirect pcrel udata8"; + case dwarf::DW_EH_PE_indirect |dwarf::DW_EH_PE_pcrel|dwarf::DW_EH_PE_sdata8: + EncStr = "indirect pcrel sdata8"; + } + + Streamer.AddComment(Twine(Prefix) + " = " + EncStr); + } + + Streamer.EmitIntValue(Encoding, 1); } void FrameEmitterImpl::EmitCFIInstruction(MCStreamer &Streamer, @@ -635,7 +669,7 @@ bool FrameEmitterImpl::EmitCompactUnwind(MCStreamer &Streamer, #else MCContext &Context = Streamer.getContext(); const TargetAsmInfo &TAI = Context.getTargetAsmInfo(); - Streamer.SwitchSection(TAI.getCompactUnwindSection()); + bool VerboseAsm = Streamer.isVerboseAsm(); // range-start range-length compact-unwind-enc personality-func lsda // _foo LfooEnd-_foo 0x00000023 0 0 @@ -659,25 +693,31 @@ bool FrameEmitterImpl::EmitCompactUnwind(MCStreamer &Streamer, // .quad __gxx_personality // .quad except_tab1 + Streamer.SwitchSection(TAI.getCompactUnwindSection()); + // Range Start unsigned FDEEncoding = TAI.getFDEEncoding(UsingCFI); unsigned Size = getSizeForEncoding(Streamer, FDEEncoding); + if (VerboseAsm) Streamer.AddComment("Range Start"); Streamer.EmitSymbolValue(Frame.Function, Size); // Range Length const MCExpr *Range = MakeStartMinusEndExpr(Streamer, *Frame.Begin, *Frame.End, 0); + if (VerboseAsm) Streamer.AddComment("Range Length"); Streamer.EmitAbsValue(Range, 4); // FIXME: // Compact Encoding + const std::vector &Moves = TAI.getInitialFrameState(); uint32_t Encoding = 0; Size = getSizeForEncoding(Streamer, dwarf::DW_EH_PE_udata4); + if (VerboseAsm) Streamer.AddComment("Compact Unwind Encoding"); Streamer.EmitIntValue(Encoding, Size); - // Personality Function Size = getSizeForEncoding(Streamer, Frame.PersonalityEncoding); + if (VerboseAsm) Streamer.AddComment("Personality Function"); if (Frame.Personality) Streamer.EmitSymbolValue(Frame.Personality, Size); else @@ -685,6 +725,7 @@ bool FrameEmitterImpl::EmitCompactUnwind(MCStreamer &Streamer, // LSDA Size = getSizeForEncoding(Streamer, Frame.LsdaEncoding); + if (VerboseAsm) Streamer.AddComment("LSDA"); if (Frame.Lsda) Streamer.EmitSymbolValue(Frame.Lsda, Size); else @@ -701,6 +742,7 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer, unsigned lsdaEncoding) { MCContext &context = streamer.getContext(); const TargetAsmInfo &asmInfo = context.getTargetAsmInfo(); + bool verboseAsm = streamer.isVerboseAsm(); MCSymbol *sectionStart; if (asmInfo.isFunctionEHFrameSymbolPrivate() || !IsEH) @@ -708,6 +750,7 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer, else sectionStart = context.GetOrCreateSymbol(Twine("EH_frame") + Twine(CIENum)); + streamer.EmitLabel(sectionStart); CIENum++; MCSymbol *sectionEnd = streamer.getContext().CreateTempSymbol(); @@ -715,19 +758,22 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer, // Length const MCExpr *Length = MakeStartMinusEndExpr(streamer, *sectionStart, *sectionEnd, 4); - streamer.EmitLabel(sectionStart); + if (verboseAsm) streamer.AddComment("CIE Length"); streamer.EmitAbsValue(Length, 4); // CIE ID unsigned CIE_ID = IsEH ? 0 : -1; + if (verboseAsm) streamer.AddComment("CIE ID Tag"); streamer.EmitIntValue(CIE_ID, 4); // Version + if (verboseAsm) streamer.AddComment("DW_CIE_VERSION"); streamer.EmitIntValue(dwarf::DW_CIE_VERSION, 1); // Augmentation String SmallString<8> Augmentation; if (IsEH) { + if (verboseAsm) streamer.AddComment("CIE Augmentation"); Augmentation += "z"; if (personality) Augmentation += "P"; @@ -739,12 +785,15 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer, streamer.EmitIntValue(0, 1); // Code Alignment Factor + if (verboseAsm) streamer.AddComment("CIE Code Alignment Factor"); streamer.EmitULEB128IntValue(1); // Data Alignment Factor + if (verboseAsm) streamer.AddComment("CIE Data Alignment Factor"); streamer.EmitSLEB128IntValue(getDataAlignmentFactor(streamer)); // Return Address Register + if (verboseAsm) streamer.AddComment("CIE Return Address Column"); streamer.EmitULEB128IntValue(asmInfo.getDwarfRARegNum(true)); // Augmentation Data Length (optional) @@ -762,19 +811,25 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer, // Encoding of the FDE pointers augmentationLength += 1; + if (verboseAsm) streamer.AddComment("Augmentation Size"); streamer.EmitULEB128IntValue(augmentationLength); // Augmentation Data (optional) if (personality) { // Personality Encoding - streamer.EmitIntValue(personalityEncoding, 1); + EmitEncodingByte(streamer, personalityEncoding, + "Personality Encoding"); // Personality + if (verboseAsm) streamer.AddComment("Personality"); EmitPersonality(streamer, *personality, personalityEncoding); } + if (lsda) - streamer.EmitIntValue(lsdaEncoding, 1); // LSDA Encoding + EmitEncodingByte(streamer, lsdaEncoding, "LSDA Encoding"); + // Encoding of the FDE pointers - streamer.EmitIntValue(asmInfo.getFDEEncoding(UsingCFI), 1); + EmitEncodingByte(streamer, asmInfo.getFDEEncoding(UsingCFI), + "FDE Encoding"); } // Initial Instructions -- cgit v1.1 From 1bd622132b3915c3cb2b044b4d57a879586bae9f Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Thu, 30 Jun 2011 21:30:30 +0000 Subject: Tweak error messages to match GCC. Should fix gcc.target/i386/pr30848.c git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134193 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86FloatingPoint.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/Target/X86/X86FloatingPoint.cpp b/lib/Target/X86/X86FloatingPoint.cpp index 3fb5493..463cde0 100644 --- a/lib/Target/X86/X86FloatingPoint.cpp +++ b/lib/Target/X86/X86FloatingPoint.cpp @@ -1467,13 +1467,13 @@ void FPS::handleSpecialFP(MachineBasicBlock::iterator &I) { } if (STUses && !isMask_32(STUses)) - report_fatal_error("Inline asm fixed inputs" + report_fatal_error("Inline asm fixed input regs" " must be last on the x87 stack"); unsigned NumSTUses = CountTrailingOnes_32(STUses); // Defs must be contiguous from the stack top. ST0-STn. if (STDefs && !isMask_32(STDefs)) - report_fatal_error("Inline asm fixed outputs" + report_fatal_error("Inline asm output regs" " must be last on the x87 stack"); unsigned NumSTDefs = CountTrailingOnes_32(STDefs); @@ -1484,7 +1484,7 @@ void FPS::handleSpecialFP(MachineBasicBlock::iterator &I) { // Popped inputs are the ones that are also clobbered or defined. unsigned STPopped = STUses & (STDefs | STClobbers); if (STPopped && !isMask_32(STPopped)) - report_fatal_error("Inline asm popped inputs" + report_fatal_error("Inline asm implicitly popped regs" " must be last on the x87 stack"); unsigned NumSTPopped = CountTrailingOnes_32(STPopped); -- cgit v1.1 From efd24ddbffc1e69fa88089de036d1873c950dfb5 Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Thu, 30 Jun 2011 21:45:12 +0000 Subject: Add more comments to the ASM output for the CIE's "moves". git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134194 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/MC/MCDwarf.cpp | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp index 82b7f8e..eb4585a 100644 --- a/lib/MC/MCDwarf.cpp +++ b/lib/MC/MCDwarf.cpp @@ -565,6 +565,7 @@ static void EmitEncodingByte(MCStreamer &Streamer, unsigned Encoding, void FrameEmitterImpl::EmitCFIInstruction(MCStreamer &Streamer, const MCCFIInstruction &Instr) { int dataAlignmentFactor = getDataAlignmentFactor(Streamer); + bool VerboseAsm = Streamer.isVerboseAsm(); switch (Instr.getOperation()) { case MCCFIInstruction::Move: @@ -576,9 +577,13 @@ void FrameEmitterImpl::EmitCFIInstruction(MCStreamer &Streamer, // If advancing cfa. if (Dst.isReg() && Dst.getReg() == MachineLocation::VirtualFP) { if (Src.getReg() == MachineLocation::VirtualFP) { + if (VerboseAsm) Streamer.AddComment("DW_CFA_def_cfa_offset"); Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_offset, 1); } else { + if (VerboseAsm) Streamer.AddComment("DW_CFA_def_cfa"); Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa, 1); + if (VerboseAsm) Streamer.AddComment(Twine("Reg ") + + Twine(Src.getReg())); Streamer.EmitULEB128IntValue(Src.getReg()); } @@ -587,47 +592,61 @@ void FrameEmitterImpl::EmitCFIInstruction(MCStreamer &Streamer, else CFAOffset = -Src.getOffset(); + if (VerboseAsm) Streamer.AddComment(Twine("Offset " + Twine(CFAOffset))); Streamer.EmitULEB128IntValue(CFAOffset); return; } if (Src.isReg() && Src.getReg() == MachineLocation::VirtualFP) { assert(Dst.isReg() && "Machine move not supported yet."); + if (VerboseAsm) Streamer.AddComment("DW_CFA_def_cfa_register"); Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_register, 1); + if (VerboseAsm) Streamer.AddComment(Twine("Reg ") + Twine(Dst.getReg())); Streamer.EmitULEB128IntValue(Dst.getReg()); return; } unsigned Reg = Src.getReg(); - int Offset = Dst.getOffset(); if (IsRelative) Offset -= CFAOffset; Offset = Offset / dataAlignmentFactor; if (Offset < 0) { + if (VerboseAsm) Streamer.AddComment("DW_CFA_offset_extended_sf"); Streamer.EmitIntValue(dwarf::DW_CFA_offset_extended_sf, 1); + if (VerboseAsm) Streamer.AddComment(Twine("Reg ") + Twine(Reg)); Streamer.EmitULEB128IntValue(Reg); + if (VerboseAsm) Streamer.AddComment(Twine("Offset ") + Twine(Offset)); Streamer.EmitSLEB128IntValue(Offset); } else if (Reg < 64) { + if (VerboseAsm) Streamer.AddComment("DW_CFA_offset"); Streamer.EmitIntValue(dwarf::DW_CFA_offset + Reg, 1); + if (VerboseAsm) Streamer.AddComment(Twine("Offset ") + Twine(Offset)); Streamer.EmitULEB128IntValue(Offset); } else { + if (VerboseAsm) Streamer.AddComment("DW_CFA_offset_extended"); Streamer.EmitIntValue(dwarf::DW_CFA_offset_extended, 1); + if (VerboseAsm) Streamer.AddComment(Twine("Reg ") + Twine(Reg)); Streamer.EmitULEB128IntValue(Reg); + if (VerboseAsm) Streamer.AddComment(Twine("Offset ") + Twine(Offset)); Streamer.EmitULEB128IntValue(Offset); } return; } case MCCFIInstruction::Remember: + if (VerboseAsm) Streamer.AddComment("DW_CFA_remember_state"); Streamer.EmitIntValue(dwarf::DW_CFA_remember_state, 1); return; case MCCFIInstruction::Restore: + if (VerboseAsm) Streamer.AddComment("DW_CFA_restore_state"); Streamer.EmitIntValue(dwarf::DW_CFA_restore_state, 1); return; case MCCFIInstruction::SameValue: { unsigned Reg = Instr.getDestination().getReg(); + if (VerboseAsm) Streamer.AddComment("DW_CFA_same_value"); Streamer.EmitIntValue(dwarf::DW_CFA_same_value, 1); + if (VerboseAsm) Streamer.AddComment(Twine("Reg ") + Twine(Reg)); Streamer.EmitULEB128IntValue(Reg); return; } -- cgit v1.1 From 2541c41f3e2af94585e14353a91f02facd65e415 Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Thu, 30 Jun 2011 22:02:20 +0000 Subject: Add comments to the FDE. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134196 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/MC/MCDwarf.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp index eb4585a..1b24464 100644 --- a/lib/MC/MCDwarf.cpp +++ b/lib/MC/MCDwarf.cpp @@ -460,13 +460,14 @@ static unsigned getSizeForEncoding(MCStreamer &streamer, } static void EmitSymbol(MCStreamer &streamer, const MCSymbol &symbol, - unsigned symbolEncoding) { + unsigned symbolEncoding, const char *comment = 0) { MCContext &context = streamer.getContext(); const MCAsmInfo &asmInfo = context.getAsmInfo(); const MCExpr *v = asmInfo.getExprForFDESymbol(&symbol, symbolEncoding, streamer); unsigned size = getSizeForEncoding(streamer, symbolEncoding); + if (streamer.isVerboseAsm() && comment) streamer.AddComment(comment); streamer.EmitAbsValue(v, size); } @@ -882,16 +883,18 @@ MCSymbol *FrameEmitterImpl::EmitFDE(MCStreamer &streamer, MCSymbol *fdeStart = context.CreateTempSymbol(); MCSymbol *fdeEnd = context.CreateTempSymbol(); const TargetAsmInfo &TAsmInfo = context.getTargetAsmInfo(); + bool verboseAsm = streamer.isVerboseAsm(); if (!TAsmInfo.isFunctionEHFrameSymbolPrivate() && IsEH) { - MCSymbol *EHSym = context.GetOrCreateSymbol( - frame.Function->getName() + Twine(".eh")); + MCSymbol *EHSym = + context.GetOrCreateSymbol(frame.Function->getName() + Twine(".eh")); streamer.EmitEHSymAttributes(frame.Function, EHSym); streamer.EmitLabel(EHSym); } // Length const MCExpr *Length = MakeStartMinusEndExpr(streamer, *fdeStart, *fdeEnd, 0); + if (verboseAsm) streamer.AddComment("FDE Length"); streamer.EmitAbsValue(Length, 4); streamer.EmitLabel(fdeStart); @@ -901,6 +904,7 @@ MCSymbol *FrameEmitterImpl::EmitFDE(MCStreamer &streamer, if (IsEH) { const MCExpr *offset = MakeStartMinusEndExpr(streamer, cieStart, *fdeStart, 0); + if (verboseAsm) streamer.AddComment("FDE CIE Offset"); streamer.EmitAbsValue(offset, 4); } else if (!asmInfo.doesDwarfRequireRelocationForSectionOffset()) { const MCExpr *offset = MakeStartMinusEndExpr(streamer, *SectionStart, @@ -909,6 +913,7 @@ MCSymbol *FrameEmitterImpl::EmitFDE(MCStreamer &streamer, } else { streamer.EmitSymbolValue(&cieStart, 4); } + unsigned fdeEncoding = TAsmInfo.getFDEEncoding(UsingCFI); unsigned size = getSizeForEncoding(streamer, fdeEncoding); @@ -916,11 +921,12 @@ MCSymbol *FrameEmitterImpl::EmitFDE(MCStreamer &streamer, unsigned PCBeginEncoding = IsEH ? fdeEncoding : (unsigned)dwarf::DW_EH_PE_absptr; unsigned PCBeginSize = getSizeForEncoding(streamer, PCBeginEncoding); - EmitSymbol(streamer, *frame.Begin, PCBeginEncoding); + EmitSymbol(streamer, *frame.Begin, PCBeginEncoding, "FDE initial location"); // PC Range const MCExpr *Range = MakeStartMinusEndExpr(streamer, *frame.Begin, *frame.End, 0); + if (verboseAsm) streamer.AddComment("FDE address range"); streamer.EmitAbsValue(Range, size); if (IsEH) { @@ -930,11 +936,13 @@ MCSymbol *FrameEmitterImpl::EmitFDE(MCStreamer &streamer, if (frame.Lsda) augmentationLength += getSizeForEncoding(streamer, frame.LsdaEncoding); + if (verboseAsm) streamer.AddComment("Augmentation size"); streamer.EmitULEB128IntValue(augmentationLength); // Augmentation Data if (frame.Lsda) - EmitSymbol(streamer, *frame.Lsda, frame.LsdaEncoding); + EmitSymbol(streamer, *frame.Lsda, frame.LsdaEncoding, + "Language Specific Data Area"); } // Call Frame Instructions -- cgit v1.1 From 63b46faeb8acae9b7e5f865b7417dc00b9b9dad3 Mon Sep 17 00:00:00 2001 From: Jim Grosbach Date: Thu, 30 Jun 2011 22:10:46 +0000 Subject: Thumb1 register to register MOV instruction is predicable. Fix a FIXME and allow predication (in Thumb2) for the T1 register to register MOV instructions. This allows some better codegen with if-conversion (as seen in the test updates), plus it lays the groundwork for pseudo-izing the tMOVCC instructions. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134197 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMAsmPrinter.cpp | 8 ++++++-- lib/Target/ARM/ARMFrameLowering.cpp | 24 ++++++++++++---------- lib/Target/ARM/ARMInstrThumb.td | 23 +++++++++++---------- lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 3 +-- lib/Target/ARM/Thumb1FrameLowering.cpp | 13 +++++++----- lib/Target/ARM/Thumb1InstrInfo.cpp | 4 ++-- lib/Target/ARM/Thumb1RegisterInfo.cpp | 22 ++++++++++---------- lib/Target/ARM/Thumb2InstrInfo.cpp | 14 ++++++------- .../Thumb2/2011-06-07-TwoAddrEarlyClobber.ll | 10 ++++----- test/CodeGen/Thumb2/thumb2-ifcvt1.ll | 5 +++-- 10 files changed, 67 insertions(+), 59 deletions(-) diff --git a/lib/Target/ARM/ARMAsmPrinter.cpp b/lib/Target/ARM/ARMAsmPrinter.cpp index 300cff5..0988ff1 100644 --- a/lib/Target/ARM/ARMAsmPrinter.cpp +++ b/lib/Target/ARM/ARMAsmPrinter.cpp @@ -1223,6 +1223,9 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { TmpInst.setOpcode(ARM::tMOVr); TmpInst.addOperand(MCOperand::CreateReg(ARM::LR)); TmpInst.addOperand(MCOperand::CreateReg(ARM::PC)); + // Add predicate operands. + TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); + TmpInst.addOperand(MCOperand::CreateReg(0)); OutStreamer.EmitInstruction(TmpInst); } { @@ -1610,8 +1613,9 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { TmpInst.setOpcode(ARM::tMOVgpr2tgpr); TmpInst.addOperand(MCOperand::CreateReg(ValReg)); TmpInst.addOperand(MCOperand::CreateReg(ARM::PC)); - // 's' bit operand - TmpInst.addOperand(MCOperand::CreateReg(ARM::CPSR)); + // Predicate. + TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); + TmpInst.addOperand(MCOperand::CreateReg(0)); OutStreamer.AddComment("eh_setjmp begin"); OutStreamer.EmitInstruction(TmpInst); } diff --git a/lib/Target/ARM/ARMFrameLowering.cpp b/lib/Target/ARM/ARMFrameLowering.cpp index 4ef2666..2b80145 100644 --- a/lib/Target/ARM/ARMFrameLowering.cpp +++ b/lib/Target/ARM/ARMFrameLowering.cpp @@ -268,14 +268,14 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF) const { // bic r4, r4, MaxAlign // mov sp, r4 // FIXME: It will be better just to find spare register here. - BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVgpr2tgpr), ARM::R4) - .addReg(ARM::SP, RegState::Kill); + AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVgpr2tgpr), ARM::R4) + .addReg(ARM::SP, RegState::Kill)); AddDefaultCC(AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::t2BICri), ARM::R4) .addReg(ARM::R4, RegState::Kill) .addImm(MaxAlign-1))); - BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVtgpr2gpr), ARM::SP) - .addReg(ARM::R4, RegState::Kill); + AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVtgpr2gpr), ARM::SP) + .addReg(ARM::R4, RegState::Kill)); } AFI->setShouldRestoreSPFromFP(true); @@ -293,9 +293,9 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF) const { .addReg(ARM::SP) .addImm((unsigned)ARMCC::AL).addReg(0).addReg(0); else - BuildMI(MBB, MBBI, dl, - TII.get(ARM::tMOVgpr2gpr), RegInfo->getBaseRegister()) - .addReg(ARM::SP); + AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVgpr2gpr), + RegInfo->getBaseRegister()) + .addReg(ARM::SP)); } // If the frame has variable sized objects then the epilogue must restore @@ -364,8 +364,9 @@ void ARMFrameLowering::emitEpilogue(MachineFunction &MF, "No scratch register to restore SP from FP!"); emitT2RegPlusImmediate(MBB, MBBI, dl, ARM::R4, FramePtr, -NumBytes, ARMCC::AL, 0, TII); - BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVgpr2gpr), ARM::SP) - .addReg(ARM::R4); + AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVgpr2gpr), + ARM::SP) + .addReg(ARM::R4)); } } else { // Thumb2 or ARM. @@ -373,8 +374,9 @@ void ARMFrameLowering::emitEpilogue(MachineFunction &MF, BuildMI(MBB, MBBI, dl, TII.get(ARM::MOVr), ARM::SP) .addReg(FramePtr).addImm((unsigned)ARMCC::AL).addReg(0).addReg(0); else - BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVgpr2gpr), ARM::SP) - .addReg(FramePtr); + AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVgpr2gpr), + ARM::SP) + .addReg(FramePtr)); } } else if (NumBytes) emitSPUpdate(isARM, MBB, MBBI, dl, TII, NumBytes); diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td index 10476335..b2bf344 100644 --- a/lib/Target/ARM/ARMInstrThumb.td +++ b/lib/Target/ARM/ARMInstrThumb.td @@ -409,7 +409,7 @@ let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in { let isReturn = 1, isTerminator = 1, isBarrier = 1, mayLoad = 1, hasExtraDefRegAllocReq = 1 in def tPOP_RET : tPseudoInst<(outs), (ins pred:$p, reglist:$regs, variable_ops), - Size4Bytes, IIC_iPop_Br, []>; + Size2Bytes, IIC_iPop_Br, []>; // All calls clobber the non-callee saved registers. SP is marked as a use to // prevent stack-pointer assignments that appear immediately before calls from @@ -1054,9 +1054,9 @@ def tMOVi8 : T1sI<(outs tGPR:$Rd), (ins imm0_255:$imm8), IIC_iMOVi, // TODO: A7-73: MOV(2) - mov setting flag. let neverHasSideEffects = 1 in { -// FIXME: Make this predicable. -def tMOVr : T1I<(outs tGPR:$Rd), (ins tGPR:$Rm), IIC_iMOVr, - "mov\t$Rd, $Rm", []>, +def tMOVr : Thumb1pI<(outs tGPR:$Rd), (ins tGPR:$Rm), AddrModeNone, + Size2Bytes, IIC_iMOVr, + "mov", "\t$Rd, $Rm", "", []>, T1Special<0b1000> { // A8.6.97 bits<4> Rd; @@ -1076,9 +1076,10 @@ def tMOVSr : T1I<(outs tGPR:$Rd), (ins tGPR:$Rm), IIC_iMOVr, let Inst{2-0} = Rd; } -// FIXME: Make these predicable. -def tMOVgpr2tgpr : T1I<(outs tGPR:$Rd), (ins GPR:$Rm), IIC_iMOVr, - "mov\t$Rd, $Rm", []>, +// FIXME: Do we really need separate instructions for GPR<-->tGPR like this? +// They all map to the same instruction (MOV encoding T1). +def tMOVgpr2tgpr : Thumb1pI<(outs tGPR:$Rd), (ins GPR:$Rm), AddrModeNone, + Size2Bytes, IIC_iMOVr, "mov", "\t$Rd, $Rm", "", []>, T1Special<{1,0,0,?}> { // A8.6.97 bits<4> Rd; @@ -1087,8 +1088,8 @@ def tMOVgpr2tgpr : T1I<(outs tGPR:$Rd), (ins GPR:$Rm), IIC_iMOVr, let Inst{6-3} = Rm; let Inst{2-0} = Rd{2-0}; } -def tMOVtgpr2gpr : T1I<(outs GPR:$Rd), (ins tGPR:$Rm), IIC_iMOVr, - "mov\t$Rd, $Rm", []>, +def tMOVtgpr2gpr : Thumb1pI<(outs GPR:$Rd), (ins tGPR:$Rm), AddrModeNone, + Size2Bytes, IIC_iMOVr, "mov", "\t$Rd, $Rm", "", []>, T1Special<{1,0,?,0}> { // A8.6.97 bits<4> Rd; @@ -1098,8 +1099,8 @@ def tMOVtgpr2gpr : T1I<(outs GPR:$Rd), (ins tGPR:$Rm), IIC_iMOVr, let Inst{5-3} = Rm{2-0}; let Inst{2-0} = Rd{2-0}; } -def tMOVgpr2gpr : T1I<(outs GPR:$Rd), (ins GPR:$Rm), IIC_iMOVr, - "mov\t$Rd, $Rm", []>, +def tMOVgpr2gpr : Thumb1pI<(outs GPR:$Rd), (ins GPR:$Rm), AddrModeNone, + Size2Bytes, IIC_iMOVr, "mov", "\t$Rd, $Rm", "", []>, T1Special<{1,0,?,?}> { // A8.6.97 bits<4> Rd; diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 178fe52..6952c38 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -1882,8 +1882,7 @@ GetMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet, if (isThumb) if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" || - Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp" || - (Mnemonic == "mov" && isThumbOne)) + Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp") CanAcceptPredicationCode = false; } diff --git a/lib/Target/ARM/Thumb1FrameLowering.cpp b/lib/Target/ARM/Thumb1FrameLowering.cpp index 80b57c9..326d4af 100644 --- a/lib/Target/ARM/Thumb1FrameLowering.cpp +++ b/lib/Target/ARM/Thumb1FrameLowering.cpp @@ -160,7 +160,8 @@ void Thumb1FrameLowering::emitPrologue(MachineFunction &MF) const { // will be allocated after this, so we can still use the base pointer // to reference locals. if (RegInfo->hasBasePointer(MF)) - BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVgpr2gpr), BasePtr).addReg(ARM::SP); + AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVgpr2gpr), BasePtr) + .addReg(ARM::SP)); // If the frame has variable sized objects then the epilogue must restore // the sp from fp. We can assume there's an FP here since hasFP already @@ -239,11 +240,13 @@ void Thumb1FrameLowering::emitEpilogue(MachineFunction &MF, "No scratch register to restore SP from FP!"); emitThumbRegPlusImmediate(MBB, MBBI, dl, ARM::R4, FramePtr, -NumBytes, TII, *RegInfo); - BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVtgpr2gpr), ARM::SP) - .addReg(ARM::R4); + AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVtgpr2gpr), + ARM::SP) + .addReg(ARM::R4)); } else - BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVtgpr2gpr), ARM::SP) - .addReg(FramePtr); + AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVtgpr2gpr), + ARM::SP) + .addReg(FramePtr)); } else { if (MBBI->getOpcode() == ARM::tBX_RET && &MBB.front() != MBBI && diff --git a/lib/Target/ARM/Thumb1InstrInfo.cpp b/lib/Target/ARM/Thumb1InstrInfo.cpp index e5d3a89..614ba81 100644 --- a/lib/Target/ARM/Thumb1InstrInfo.cpp +++ b/lib/Target/ARM/Thumb1InstrInfo.cpp @@ -46,8 +46,8 @@ void Thumb1InstrInfo::copyPhysReg(MachineBasicBlock &MBB, else if (tDest) Opc = ARM::tMOVgpr2tgpr; - BuildMI(MBB, I, DL, get(Opc), DestReg) - .addReg(SrcReg, getKillRegState(KillSrc)); + AddDefaultPred(BuildMI(MBB, I, DL, get(Opc), DestReg) + .addReg(SrcReg, getKillRegState(KillSrc))); assert(ARM::GPRRegClass.contains(DestReg, SrcReg) && "Thumb1 can only copy GPR registers"); } diff --git a/lib/Target/ARM/Thumb1RegisterInfo.cpp b/lib/Target/ARM/Thumb1RegisterInfo.cpp index c485c8e..95fbe8c 100644 --- a/lib/Target/ARM/Thumb1RegisterInfo.cpp +++ b/lib/Target/ARM/Thumb1RegisterInfo.cpp @@ -244,8 +244,8 @@ void llvm::emitThumbRegPlusImmediate(MachineBasicBlock &MBB, AddDefaultT1CC(BuildMI(MBB, MBBI, dl, MCID, DestReg).setMIFlags(MIFlags)); AddDefaultPred(MIB.addReg(BaseReg, RegState::Kill).addImm(ThisVal)); } else { - BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), DestReg) - .addReg(BaseReg, RegState::Kill) + AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), DestReg) + .addReg(BaseReg, RegState::Kill)) .setMIFlags(MIFlags); } BaseReg = DestReg; @@ -419,11 +419,10 @@ rewriteFrameIndex(MachineBasicBlock::iterator II, unsigned FrameRegIdx, // Turn it into a move. MI.setDesc(TII.get(ARM::tMOVgpr2tgpr)); MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); - // Remove offset and remaining explicit predicate operands. - do MI.RemoveOperand(FrameRegIdx+1); - while (MI.getNumOperands() > FrameRegIdx+1 && - (!MI.getOperand(FrameRegIdx+1).isReg() || - !MI.getOperand(FrameRegIdx+1).isImm())); + // Remove offset and add predicate operands. + MI.RemoveOperand(FrameRegIdx+1); + MachineInstrBuilder MIB(&MI); + AddDefaultPred(MIB); return true; } @@ -565,8 +564,9 @@ Thumb1RegisterInfo::saveScavengerRegister(MachineBasicBlock &MBB, // the function, the offset will be negative. Use R12 instead since that's // a call clobbered register that we know won't be used in Thumb1 mode. DebugLoc DL; - BuildMI(MBB, I, DL, TII.get(ARM::tMOVtgpr2gpr)). - addReg(ARM::R12, RegState::Define).addReg(Reg, RegState::Kill); + AddDefaultPred(BuildMI(MBB, I, DL, TII.get(ARM::tMOVtgpr2gpr)) + .addReg(ARM::R12, RegState::Define) + .addReg(Reg, RegState::Kill)); // The UseMI is where we would like to restore the register. If there's // interference with R12 before then, however, we'll need to restore it @@ -589,8 +589,8 @@ Thumb1RegisterInfo::saveScavengerRegister(MachineBasicBlock &MBB, } } // Restore the register from R12 - BuildMI(MBB, UseMI, DL, TII.get(ARM::tMOVgpr2tgpr)). - addReg(Reg, RegState::Define).addReg(ARM::R12, RegState::Kill); + AddDefaultPred(BuildMI(MBB, UseMI, DL, TII.get(ARM::tMOVgpr2tgpr)). + addReg(Reg, RegState::Define).addReg(ARM::R12, RegState::Kill)); return true; } diff --git a/lib/Target/ARM/Thumb2InstrInfo.cpp b/lib/Target/ARM/Thumb2InstrInfo.cpp index b1991f1..d958693 100644 --- a/lib/Target/ARM/Thumb2InstrInfo.cpp +++ b/lib/Target/ARM/Thumb2InstrInfo.cpp @@ -122,8 +122,8 @@ void Thumb2InstrInfo::copyPhysReg(MachineBasicBlock &MBB, else if (tDest) Opc = ARM::tMOVgpr2tgpr; - BuildMI(MBB, I, DL, get(Opc), DestReg) - .addReg(SrcReg, getKillRegState(KillSrc)); + AddDefaultPred(BuildMI(MBB, I, DL, get(Opc), DestReg) + .addReg(SrcReg, getKillRegState(KillSrc))); } void Thumb2InstrInfo:: @@ -231,8 +231,8 @@ void llvm::emitT2RegPlusImmediate(MachineBasicBlock &MBB, unsigned Opc = 0; if (DestReg == ARM::SP && BaseReg != ARM::SP) { // mov sp, rn. Note t2MOVr cannot be used. - BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVgpr2gpr),DestReg) - .addReg(BaseReg).setMIFlags(MIFlags); + AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVgpr2gpr),DestReg) + .addReg(BaseReg).setMIFlags(MIFlags)); BaseReg = ARM::SP; continue; } @@ -413,9 +413,9 @@ bool llvm::rewriteT2FrameIndex(MachineInstr &MI, unsigned FrameRegIdx, MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); // Remove offset and remaining explicit predicate operands. do MI.RemoveOperand(FrameRegIdx+1); - while (MI.getNumOperands() > FrameRegIdx+1 && - (!MI.getOperand(FrameRegIdx+1).isReg() || - !MI.getOperand(FrameRegIdx+1).isImm())); + while (MI.getNumOperands() > FrameRegIdx+1); + MachineInstrBuilder MIB(&MI); + AddDefaultPred(MIB); return true; } diff --git a/test/CodeGen/Thumb2/2011-06-07-TwoAddrEarlyClobber.ll b/test/CodeGen/Thumb2/2011-06-07-TwoAddrEarlyClobber.ll index 9e6d78e..b1ce3bb 100644 --- a/test/CodeGen/Thumb2/2011-06-07-TwoAddrEarlyClobber.ll +++ b/test/CodeGen/Thumb2/2011-06-07-TwoAddrEarlyClobber.ll @@ -1,13 +1,11 @@ -; RUN: llc < %s | FileCheck %s -target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:32:64-v128:32:128-a0:0:32-n32" -target triple = "thumbv7-apple-darwin10" +; RUN: llc -mtriple=thumbv7-apple-darwin10 < %s | FileCheck %s %struct.op = type { %struct.op*, %struct.op*, %struct.op* ()*, i32, i16, i16, i8, i8 } ; CHECK: Perl_ck_sort -; CHECK: ldr -; CHECK: mov [[REGISTER:(r[0-9]+)|(lr)]] -; CHECK: str {{(r[0-9])|(lr)}}, {{\[}}[[REGISTER]]{{\]}}, #24 +; CHECK: ldreq +; CHECK: moveq [[REGISTER:(r[0-9]+)|(lr)]] +; CHECK: streq {{(r[0-9])|(lr)}}, {{\[}}[[REGISTER]]{{\]}}, #24 define void @Perl_ck_sort() nounwind optsize { entry: diff --git a/test/CodeGen/Thumb2/thumb2-ifcvt1.ll b/test/CodeGen/Thumb2/thumb2-ifcvt1.ll index d842d4d..1533040 100644 --- a/test/CodeGen/Thumb2/thumb2-ifcvt1.ll +++ b/test/CodeGen/Thumb2/thumb2-ifcvt1.ll @@ -70,8 +70,9 @@ entry: define void @t3(i32 %a, i32 %b) nounwind { entry: ; CHECK: t3: -; CHECK: it lt -; CHECK: poplt {r7, pc} +; CHECK: itt ge +; CHECK: movge r0, r1 +; CHECK: blge _foo %tmp1 = icmp sgt i32 %a, 10 ; [#uses=1] br i1 %tmp1, label %cond_true, label %UnifiedReturnBlock -- cgit v1.1 From a8cca80d4ac9ad94223b31e1c2203a30825529ed Mon Sep 17 00:00:00 2001 From: Eric Christopher Date: Thu, 30 Jun 2011 22:17:01 +0000 Subject: Add a convenience typedef for std::pair. No functional change. Part of rdar://9119939 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134198 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMISelLowering.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index 507cc60..092ff17 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -7527,7 +7527,8 @@ ARMTargetLowering::getSingleConstraintMatchWeight( return weight; } -std::pair +typedef std::pair Pair; +Pair ARMTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const { if (Constraint.size() == 1) { @@ -7535,18 +7536,18 @@ ARMTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint, switch (Constraint[0]) { case 'l': if (Subtarget->isThumb()) - return std::make_pair(0U, ARM::tGPRRegisterClass); + return Pair(0U, ARM::tGPRRegisterClass); else - return std::make_pair(0U, ARM::GPRRegisterClass); + return Pair(0U, ARM::GPRRegisterClass); case 'r': - return std::make_pair(0U, ARM::GPRRegisterClass); + return Pair(0U, ARM::GPRRegisterClass); case 'w': if (VT == MVT::f32) - return std::make_pair(0U, ARM::SPRRegisterClass); + return Pair(0U, ARM::SPRRegisterClass); if (VT.getSizeInBits() == 64) - return std::make_pair(0U, ARM::DPRRegisterClass); + return Pair(0U, ARM::DPRRegisterClass); if (VT.getSizeInBits() == 128) - return std::make_pair(0U, ARM::QPRRegisterClass); + return Pair(0U, ARM::QPRRegisterClass); break; } } -- cgit v1.1 From c747acb8d97d4df51d738383b49b8115519b88fb Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Thu, 30 Jun 2011 22:24:13 +0000 Subject: Don't give up on coalescing A and B when we find A = X B = X Instead, proceed as if we had found A = X B = A git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134199 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/RegisterCoalescer.cpp | 105 ++++++++++++++++++++++++++++++++++---- 1 file changed, 95 insertions(+), 10 deletions(-) diff --git a/lib/CodeGen/RegisterCoalescer.cpp b/lib/CodeGen/RegisterCoalescer.cpp index 3b8a3e8..e9c038d 100644 --- a/lib/CodeGen/RegisterCoalescer.cpp +++ b/lib/CodeGen/RegisterCoalescer.cpp @@ -1187,6 +1187,65 @@ static unsigned ComputeUltimateVN(VNInfo *VNI, return ThisValNoAssignments[VN] = UltimateVN; } + +// Find out if we have something like +// A = X +// B = X +// if so, we can pretend this is actually +// A = X +// B = A +// which allows us to coalesce A and B. +// MI is the definition of B. LR is the life range of A that includes +// the slot just before B. If we return true, we add "B = X" to DupCopies. +static bool RegistersDefinedFromSameValue(const TargetRegisterInfo &tri, + CoalescerPair &CP, MachineInstr *MI, + LiveRange *LR, + SmallVector &DupCopies) { + // FIXME: This is very conservative. For example, we don't handle + // physical registers. + + if (!MI->isFullCopy() || CP.isPartial() || CP.isPhys()) + return false; + + unsigned Dst = MI->getOperand(0).getReg(); + unsigned Src = MI->getOperand(1).getReg(); + + if (!TargetRegisterInfo::isVirtualRegister(Src) || + !TargetRegisterInfo::isVirtualRegister(Dst)) + return false; + + unsigned A = CP.getDstReg(); + unsigned B = CP.getSrcReg(); + + if (B == Dst) + std::swap(A, B); + assert(Dst == A); + + VNInfo *Other = LR->valno; + if (!Other->isDefByCopy()) + return false; + const MachineInstr *OtherMI = Other->getCopy(); + + if (!OtherMI->isFullCopy()) + return false; + + unsigned OtherDst = OtherMI->getOperand(0).getReg(); + unsigned OtherSrc = OtherMI->getOperand(1).getReg(); + + if (!TargetRegisterInfo::isVirtualRegister(OtherSrc) || + !TargetRegisterInfo::isVirtualRegister(OtherDst)) + return false; + + assert(OtherDst == B); + + if (Src != OtherSrc) + return false; + + DupCopies.push_back(MI); + + return true; +} + /// JoinIntervals - Attempt to join these two intervals. On failure, this /// returns false. bool RegisterCoalescer::JoinIntervals(CoalescerPair &CP) { @@ -1242,6 +1301,8 @@ bool RegisterCoalescer::JoinIntervals(CoalescerPair &CP) { DenseMap RHSValsDefinedFromLHS; SmallVector NewVNInfo; + SmallVector DupCopies; + LiveInterval &LHS = li_->getOrCreateInterval(CP.getDstReg()); DEBUG({ dbgs() << "\t\tLHS = "; LHS.print(dbgs(), tri_); dbgs() << "\n"; }); @@ -1257,15 +1318,18 @@ bool RegisterCoalescer::JoinIntervals(CoalescerPair &CP) { if (VNI->hasRedefByEC()) return false; - // DstReg is known to be a register in the LHS interval. If the src is - // from the RHS interval, we can use its value #. - if (!CP.isCoalescable(VNI->getCopy())) - continue; - // Figure out the value # from the RHS. LiveRange *lr = RHS.getLiveRangeContaining(VNI->def.getPrevSlot()); // The copy could be to an aliased physreg. if (!lr) continue; + + // DstReg is known to be a register in the LHS interval. If the src is + // from the RHS interval, we can use its value #. + MachineInstr *MI = VNI->getCopy(); + if (!CP.isCoalescable(MI) && + !RegistersDefinedFromSameValue(*tri_, CP, MI, lr, DupCopies)) + continue; + LHSValsDefinedFromRHS[VNI] = lr->valno; } @@ -1281,15 +1345,18 @@ bool RegisterCoalescer::JoinIntervals(CoalescerPair &CP) { if (VNI->hasRedefByEC()) return false; - // DstReg is known to be a register in the RHS interval. If the src is - // from the LHS interval, we can use its value #. - if (!CP.isCoalescable(VNI->getCopy())) - continue; - // Figure out the value # from the LHS. LiveRange *lr = LHS.getLiveRangeContaining(VNI->def.getPrevSlot()); // The copy could be to an aliased physreg. if (!lr) continue; + + // DstReg is known to be a register in the RHS interval. If the src is + // from the LHS interval, we can use its value #. + MachineInstr *MI = VNI->getCopy(); + if (!CP.isCoalescable(MI) && + !RegistersDefinedFromSameValue(*tri_, CP, MI, lr, DupCopies)) + continue; + RHSValsDefinedFromLHS[VNI] = lr->valno; } @@ -1394,6 +1461,24 @@ bool RegisterCoalescer::JoinIntervals(CoalescerPair &CP) { if (RHSValNoAssignments.empty()) RHSValNoAssignments.push_back(-1); + for (SmallVector::iterator I = DupCopies.begin(), + E = DupCopies.end(); I != E; ++I) { + MachineInstr *MI = *I; + + // We have pretended that the assignment to B in + // A = X + // B = X + // was actually a copy from A. Now that we decided to coalesce A and B, + // transform the code into + // A = X + // X = X + // and mark the X as coalesced to keep the illusion. + unsigned Src = MI->getOperand(1).getReg(); + MI->getOperand(0).substVirtReg(Src, 0, *tri_); + + markAsJoined(MI); + } + // If we get here, we know that we can coalesce the live ranges. Ask the // intervals to coalesce themselves now. LHS.join(RHS, &LHSValNoAssignments[0], &RHSValNoAssignments[0], NewVNInfo, -- cgit v1.1 From d221cd676b44d8118b1db152ecc2168538479626 Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Thu, 30 Jun 2011 22:35:49 +0000 Subject: Add one more comment to the FDE verbose asm output. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134200 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/MC/MCDwarf.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp index 1b24464..1a3596a 100644 --- a/lib/MC/MCDwarf.cpp +++ b/lib/MC/MCDwarf.cpp @@ -670,6 +670,7 @@ void FrameEmitterImpl::EmitCFIInstructions(MCStreamer &streamer, if (BaseLabel && Label) { MCSymbol *ThisSym = Label; if (ThisSym != BaseLabel) { + if (streamer.isVerboseAsm()) streamer.AddComment("DW_CFA_advance_loc4"); streamer.EmitDwarfAdvanceFrameAddr(BaseLabel, ThisSym); BaseLabel = ThisSym; } -- cgit v1.1 From 15e96be3c70ab2e4a50c505c2b90e4ce1095dbd6 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Thu, 30 Jun 2011 22:58:17 +0000 Subject: Revert my previous patch while I debug llvm-gcc bootstrap. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134201 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/RegisterCoalescer.cpp | 105 ++++---------------------------------- 1 file changed, 10 insertions(+), 95 deletions(-) diff --git a/lib/CodeGen/RegisterCoalescer.cpp b/lib/CodeGen/RegisterCoalescer.cpp index e9c038d..3b8a3e8 100644 --- a/lib/CodeGen/RegisterCoalescer.cpp +++ b/lib/CodeGen/RegisterCoalescer.cpp @@ -1187,65 +1187,6 @@ static unsigned ComputeUltimateVN(VNInfo *VNI, return ThisValNoAssignments[VN] = UltimateVN; } - -// Find out if we have something like -// A = X -// B = X -// if so, we can pretend this is actually -// A = X -// B = A -// which allows us to coalesce A and B. -// MI is the definition of B. LR is the life range of A that includes -// the slot just before B. If we return true, we add "B = X" to DupCopies. -static bool RegistersDefinedFromSameValue(const TargetRegisterInfo &tri, - CoalescerPair &CP, MachineInstr *MI, - LiveRange *LR, - SmallVector &DupCopies) { - // FIXME: This is very conservative. For example, we don't handle - // physical registers. - - if (!MI->isFullCopy() || CP.isPartial() || CP.isPhys()) - return false; - - unsigned Dst = MI->getOperand(0).getReg(); - unsigned Src = MI->getOperand(1).getReg(); - - if (!TargetRegisterInfo::isVirtualRegister(Src) || - !TargetRegisterInfo::isVirtualRegister(Dst)) - return false; - - unsigned A = CP.getDstReg(); - unsigned B = CP.getSrcReg(); - - if (B == Dst) - std::swap(A, B); - assert(Dst == A); - - VNInfo *Other = LR->valno; - if (!Other->isDefByCopy()) - return false; - const MachineInstr *OtherMI = Other->getCopy(); - - if (!OtherMI->isFullCopy()) - return false; - - unsigned OtherDst = OtherMI->getOperand(0).getReg(); - unsigned OtherSrc = OtherMI->getOperand(1).getReg(); - - if (!TargetRegisterInfo::isVirtualRegister(OtherSrc) || - !TargetRegisterInfo::isVirtualRegister(OtherDst)) - return false; - - assert(OtherDst == B); - - if (Src != OtherSrc) - return false; - - DupCopies.push_back(MI); - - return true; -} - /// JoinIntervals - Attempt to join these two intervals. On failure, this /// returns false. bool RegisterCoalescer::JoinIntervals(CoalescerPair &CP) { @@ -1301,8 +1242,6 @@ bool RegisterCoalescer::JoinIntervals(CoalescerPair &CP) { DenseMap RHSValsDefinedFromLHS; SmallVector NewVNInfo; - SmallVector DupCopies; - LiveInterval &LHS = li_->getOrCreateInterval(CP.getDstReg()); DEBUG({ dbgs() << "\t\tLHS = "; LHS.print(dbgs(), tri_); dbgs() << "\n"; }); @@ -1318,18 +1257,15 @@ bool RegisterCoalescer::JoinIntervals(CoalescerPair &CP) { if (VNI->hasRedefByEC()) return false; - // Figure out the value # from the RHS. - LiveRange *lr = RHS.getLiveRangeContaining(VNI->def.getPrevSlot()); - // The copy could be to an aliased physreg. - if (!lr) continue; - // DstReg is known to be a register in the LHS interval. If the src is // from the RHS interval, we can use its value #. - MachineInstr *MI = VNI->getCopy(); - if (!CP.isCoalescable(MI) && - !RegistersDefinedFromSameValue(*tri_, CP, MI, lr, DupCopies)) + if (!CP.isCoalescable(VNI->getCopy())) continue; + // Figure out the value # from the RHS. + LiveRange *lr = RHS.getLiveRangeContaining(VNI->def.getPrevSlot()); + // The copy could be to an aliased physreg. + if (!lr) continue; LHSValsDefinedFromRHS[VNI] = lr->valno; } @@ -1345,18 +1281,15 @@ bool RegisterCoalescer::JoinIntervals(CoalescerPair &CP) { if (VNI->hasRedefByEC()) return false; + // DstReg is known to be a register in the RHS interval. If the src is + // from the LHS interval, we can use its value #. + if (!CP.isCoalescable(VNI->getCopy())) + continue; + // Figure out the value # from the LHS. LiveRange *lr = LHS.getLiveRangeContaining(VNI->def.getPrevSlot()); // The copy could be to an aliased physreg. if (!lr) continue; - - // DstReg is known to be a register in the RHS interval. If the src is - // from the LHS interval, we can use its value #. - MachineInstr *MI = VNI->getCopy(); - if (!CP.isCoalescable(MI) && - !RegistersDefinedFromSameValue(*tri_, CP, MI, lr, DupCopies)) - continue; - RHSValsDefinedFromLHS[VNI] = lr->valno; } @@ -1461,24 +1394,6 @@ bool RegisterCoalescer::JoinIntervals(CoalescerPair &CP) { if (RHSValNoAssignments.empty()) RHSValNoAssignments.push_back(-1); - for (SmallVector::iterator I = DupCopies.begin(), - E = DupCopies.end(); I != E; ++I) { - MachineInstr *MI = *I; - - // We have pretended that the assignment to B in - // A = X - // B = X - // was actually a copy from A. Now that we decided to coalesce A and B, - // transform the code into - // A = X - // X = X - // and mark the X as coalesced to keep the illusion. - unsigned Src = MI->getOperand(1).getReg(); - MI->getOperand(0).substVirtReg(Src, 0, *tri_); - - markAsJoined(MI); - } - // If we get here, we know that we can coalesce the live ranges. Ask the // intervals to coalesce themselves now. LHS.join(RHS, &LHSValNoAssignments[0], &RHSValNoAssignments[0], NewVNInfo, -- cgit v1.1 From 5cd2791513919ee7504c309151321e4e37a05a58 Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Thu, 30 Jun 2011 23:20:32 +0000 Subject: Add target a target hook to get the register number used by the compact unwind encoding for the registers it knows about. Return -1 if it can't handle that register. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134202 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Target/TargetAsmInfo.h | 4 ++++ include/llvm/Target/TargetRegisterInfo.h | 6 ++++++ lib/Target/X86/X86RegisterInfo.cpp | 15 +++++++++++++++ lib/Target/X86/X86RegisterInfo.h | 4 ++++ 4 files changed, 29 insertions(+) diff --git a/include/llvm/Target/TargetAsmInfo.h b/include/llvm/Target/TargetAsmInfo.h index abaed81..1a417a1 100644 --- a/include/llvm/Target/TargetAsmInfo.h +++ b/include/llvm/Target/TargetAsmInfo.h @@ -106,6 +106,10 @@ public: int getSEHRegNum(unsigned RegNum) const { return TRI->getSEHRegNum(RegNum); } + + int getCompactUnwindRegNum(unsigned RegNum) const { + return TRI->getCompactUnwindRegNum(RegNum); + } }; } diff --git a/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h index 2965b1d..3f28f6c 100644 --- a/include/llvm/Target/TargetRegisterInfo.h +++ b/include/llvm/Target/TargetRegisterInfo.h @@ -720,6 +720,12 @@ public: virtual int getSEHRegNum(unsigned i) const { return i; } + + /// getCompactUnwindRegNum - This function maps the register to the number for + /// compact unwind encoding. Return -1 if the register isn't valid. + virtual int getCompactUnwindRegNum(unsigned) const { + return -1; + } }; diff --git a/lib/Target/X86/X86RegisterInfo.cpp b/lib/Target/X86/X86RegisterInfo.cpp index c0ce81a..20f8992 100644 --- a/lib/Target/X86/X86RegisterInfo.cpp +++ b/lib/Target/X86/X86RegisterInfo.cpp @@ -105,6 +105,21 @@ int X86RegisterInfo::getLLVMRegNum(unsigned DwarfRegNo, bool isEH) const { return X86GenRegisterInfo::getLLVMRegNumFull(DwarfRegNo, Flavour); } +/// getCompactUnwindRegNum - This function maps the register to the number for +/// compact unwind encoding. Return -1 if the register isn't valid. +int X86RegisterInfo::getCompactUnwindRegNum(unsigned RegNum) const { + switch (RegNum) { + case X86::EBX: case X86::RBX: return 1; + case X86::ECX: case X86::RCX: return 2; + case X86::EDX: case X86::RDX: return 3; + case X86::EDI: case X86::RDI: return 4; + case X86::ESI: case X86::RSI: return 5; + case X86::EBP: case X86::RBP: return 6; + } + + return -1; +} + int X86RegisterInfo::getSEHRegNum(unsigned i) const { int reg = getX86RegNum(i); diff --git a/lib/Target/X86/X86RegisterInfo.h b/lib/Target/X86/X86RegisterInfo.h index 0c014a6..a09c7ee 100644 --- a/lib/Target/X86/X86RegisterInfo.h +++ b/lib/Target/X86/X86RegisterInfo.h @@ -81,6 +81,10 @@ public: // FIXME: This should be tablegen'd like getDwarfRegNum is int getSEHRegNum(unsigned i) const; + /// getCompactUnwindRegNum - This function maps the register to the number for + /// compact unwind encoding. Return -1 if the register isn't valid. + int getCompactUnwindRegNum(unsigned RegNum) const; + /// Code Generation virtual methods... /// -- cgit v1.1 From 73744df0c467895bac9e25d5c62f34a0a8fcc4f9 Mon Sep 17 00:00:00 2001 From: Eric Christopher Date: Thu, 30 Jun 2011 23:23:01 +0000 Subject: Add support for the 'h' constraint. Part of rdar://9119939 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134203 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMISelLowering.cpp | 8 +++++++- lib/Target/ARM/ARMRegisterInfo.td | 3 +++ test/CodeGen/Thumb/inlineasm-thumb.ll | 7 +++++++ 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 test/CodeGen/Thumb/inlineasm-thumb.ll diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index 092ff17..1b9bcc9 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -7482,6 +7482,7 @@ ARMTargetLowering::getConstraintType(const std::string &Constraint) const { default: break; case 'l': return C_RegisterClass; case 'w': return C_RegisterClass; + case 'h': return C_RegisterClass; } } else if (Constraint.size() == 2) { switch (Constraint[0]) { @@ -7534,11 +7535,16 @@ ARMTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint, if (Constraint.size() == 1) { // GCC ARM Constraint Letters switch (Constraint[0]) { - case 'l': + case 'l': // Low regs or general regs. if (Subtarget->isThumb()) return Pair(0U, ARM::tGPRRegisterClass); else return Pair(0U, ARM::GPRRegisterClass); + case 'h': // High regs or no regs. + if (Subtarget->isThumb()) + return Pair(0U, ARM::hGPRRegisterClass); + else + return Pair(0u, static_cast(0)); case 'r': return Pair(0U, ARM::GPRRegisterClass); case 'w': diff --git a/lib/Target/ARM/ARMRegisterInfo.td b/lib/Target/ARM/ARMRegisterInfo.td index 7741410..76eb496 100644 --- a/lib/Target/ARM/ARMRegisterInfo.td +++ b/lib/Target/ARM/ARMRegisterInfo.td @@ -228,6 +228,9 @@ def rGPR : RegisterClass<"ARM", [i32], 32, (sub GPR, SP, PC)> { // the general GPR register class above (MOV, e.g.) def tGPR : RegisterClass<"ARM", [i32], 32, (trunc GPR, 8)>; +// The high registers in thumb mode, R8-R15. +def hGPR : RegisterClass<"ARM", [i32], 32, (sub GPR, tGPR)>; + // For tail calls, we can't use callee-saved registers, as they are restored // to the saved value before the tail call, which would clobber a call address. // Note, getMinimalPhysRegClass(R0) returns tGPR because of the names of diff --git a/test/CodeGen/Thumb/inlineasm-thumb.ll b/test/CodeGen/Thumb/inlineasm-thumb.ll new file mode 100644 index 0000000..f2683c8 --- /dev/null +++ b/test/CodeGen/Thumb/inlineasm-thumb.ll @@ -0,0 +1,7 @@ +; RUN: llc < %s -march=thumb | FileCheck %s +define i32 @t1(i32 %x, i32 %y) nounwind { +entry: + ; CHECK: mov r0, r12 + %0 = tail call i32 asm "mov $0, $1", "=l,h"(i32 %y) nounwind + ret i32 %0 +} -- cgit v1.1 From 2a7b41ba4d3eb3c6003f6768dc20b28d83eac265 Mon Sep 17 00:00:00 2001 From: Jim Grosbach Date: Thu, 30 Jun 2011 23:38:17 +0000 Subject: Refact ARM Thumb1 tMOVr instruction family. Merge the tMOVr, tMOVgpr2tgpr, tMOVtgpr2gpr, and tMOVgpr2gpr instructions into tMOVr. There's no need to keep them separate. Giving the tMOVr instruction the proper GPR register class for its operands is sufficient to give the register allocator enough information to do the right thing directly. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134204 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMAsmPrinter.cpp | 12 ++++------ lib/Target/ARM/ARMFrameLowering.cpp | 10 ++++---- lib/Target/ARM/ARMInstrThumb.td | 42 ++++------------------------------ lib/Target/ARM/Thumb1FrameLowering.cpp | 6 ++--- lib/Target/ARM/Thumb1InstrInfo.cpp | 12 +--------- lib/Target/ARM/Thumb1RegisterInfo.cpp | 6 ++--- lib/Target/ARM/Thumb2ITBlockPass.cpp | 3 --- lib/Target/ARM/Thumb2InstrInfo.cpp | 19 ++++----------- lib/Target/ARM/Thumb2SizeReduction.cpp | 2 +- 9 files changed, 26 insertions(+), 86 deletions(-) diff --git a/lib/Target/ARM/ARMAsmPrinter.cpp b/lib/Target/ARM/ARMAsmPrinter.cpp index 0988ff1..7240837 100644 --- a/lib/Target/ARM/ARMAsmPrinter.cpp +++ b/lib/Target/ARM/ARMAsmPrinter.cpp @@ -1010,8 +1010,6 @@ void ARMAsmPrinter::EmitUnwindingInstruction(const MachineInstr *MI) { MI->dump(); assert(0 && "Unsupported opcode for unwinding information"); case ARM::MOVr: - case ARM::tMOVgpr2gpr: - case ARM::tMOVgpr2tgpr: Offset = 0; break; case ARM::ADDri: @@ -1456,7 +1454,7 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { case ARM::t2BR_JT: { // Lower and emit the instruction itself, then the jump table following it. MCInst TmpInst; - TmpInst.setOpcode(ARM::tMOVgpr2gpr); + TmpInst.setOpcode(ARM::tMOVr); TmpInst.addOperand(MCOperand::CreateReg(ARM::PC)); TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg())); // Add predicate operands. @@ -1505,7 +1503,7 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { // mov pc, target MCInst TmpInst; unsigned Opc = MI->getOpcode() == ARM::BR_JTr ? - ARM::MOVr : ARM::tMOVgpr2gpr; + ARM::MOVr : ARM::tMOVr; TmpInst.setOpcode(Opc); TmpInst.addOperand(MCOperand::CreateReg(ARM::PC)); TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg())); @@ -1518,7 +1516,7 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { OutStreamer.EmitInstruction(TmpInst); // Make sure the Thumb jump table is 4-byte aligned. - if (Opc == ARM::tMOVgpr2gpr) + if (Opc == ARM::tMOVr) EmitAlignment(2); // Output the data for the jump table itself @@ -1610,7 +1608,7 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { MCSymbol *Label = GetARMSJLJEHLabel(); { MCInst TmpInst; - TmpInst.setOpcode(ARM::tMOVgpr2tgpr); + TmpInst.setOpcode(ARM::tMOVr); TmpInst.addOperand(MCOperand::CreateReg(ValReg)); TmpInst.addOperand(MCOperand::CreateReg(ARM::PC)); // Predicate. @@ -1829,7 +1827,7 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { } { MCInst TmpInst; - TmpInst.setOpcode(ARM::tMOVtgpr2gpr); + TmpInst.setOpcode(ARM::tMOVr); TmpInst.addOperand(MCOperand::CreateReg(ARM::SP)); TmpInst.addOperand(MCOperand::CreateReg(ScratchReg)); // Predicate. diff --git a/lib/Target/ARM/ARMFrameLowering.cpp b/lib/Target/ARM/ARMFrameLowering.cpp index 2b80145..9e943e4 100644 --- a/lib/Target/ARM/ARMFrameLowering.cpp +++ b/lib/Target/ARM/ARMFrameLowering.cpp @@ -268,13 +268,13 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF) const { // bic r4, r4, MaxAlign // mov sp, r4 // FIXME: It will be better just to find spare register here. - AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVgpr2tgpr), ARM::R4) + AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), ARM::R4) .addReg(ARM::SP, RegState::Kill)); AddDefaultCC(AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::t2BICri), ARM::R4) .addReg(ARM::R4, RegState::Kill) .addImm(MaxAlign-1))); - AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVtgpr2gpr), ARM::SP) + AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), ARM::SP) .addReg(ARM::R4, RegState::Kill)); } @@ -293,7 +293,7 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF) const { .addReg(ARM::SP) .addImm((unsigned)ARMCC::AL).addReg(0).addReg(0); else - AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVgpr2gpr), + AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), RegInfo->getBaseRegister()) .addReg(ARM::SP)); } @@ -364,7 +364,7 @@ void ARMFrameLowering::emitEpilogue(MachineFunction &MF, "No scratch register to restore SP from FP!"); emitT2RegPlusImmediate(MBB, MBBI, dl, ARM::R4, FramePtr, -NumBytes, ARMCC::AL, 0, TII); - AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVgpr2gpr), + AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), ARM::SP) .addReg(ARM::R4)); } @@ -374,7 +374,7 @@ void ARMFrameLowering::emitEpilogue(MachineFunction &MF, BuildMI(MBB, MBBI, dl, TII.get(ARM::MOVr), ARM::SP) .addReg(FramePtr).addImm((unsigned)ARMCC::AL).addReg(0).addReg(0); else - AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVgpr2gpr), + AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), ARM::SP) .addReg(FramePtr)); } diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td index b2bf344..0b14976 100644 --- a/lib/Target/ARM/ARMInstrThumb.td +++ b/lib/Target/ARM/ARMInstrThumb.td @@ -1054,15 +1054,15 @@ def tMOVi8 : T1sI<(outs tGPR:$Rd), (ins imm0_255:$imm8), IIC_iMOVi, // TODO: A7-73: MOV(2) - mov setting flag. let neverHasSideEffects = 1 in { -def tMOVr : Thumb1pI<(outs tGPR:$Rd), (ins tGPR:$Rm), AddrModeNone, +def tMOVr : Thumb1pI<(outs GPR:$Rd), (ins GPR:$Rm), AddrModeNone, Size2Bytes, IIC_iMOVr, "mov", "\t$Rd, $Rm", "", []>, - T1Special<0b1000> { + T1Special<{1,0,?,?}> { // A8.6.97 bits<4> Rd; bits<4> Rm; - // Bits {7-6} are encoded by the T1Special value. - let Inst{5-3} = Rm{2-0}; + let Inst{7} = Rd{3}; + let Inst{6-3} = Rm; let Inst{2-0} = Rd{2-0}; } let Defs = [CPSR] in @@ -1075,40 +1075,6 @@ def tMOVSr : T1I<(outs tGPR:$Rd), (ins tGPR:$Rm), IIC_iMOVr, let Inst{5-3} = Rm; let Inst{2-0} = Rd; } - -// FIXME: Do we really need separate instructions for GPR<-->tGPR like this? -// They all map to the same instruction (MOV encoding T1). -def tMOVgpr2tgpr : Thumb1pI<(outs tGPR:$Rd), (ins GPR:$Rm), AddrModeNone, - Size2Bytes, IIC_iMOVr, "mov", "\t$Rd, $Rm", "", []>, - T1Special<{1,0,0,?}> { - // A8.6.97 - bits<4> Rd; - bits<4> Rm; - // Bit {7} is encoded by the T1Special value. - let Inst{6-3} = Rm; - let Inst{2-0} = Rd{2-0}; -} -def tMOVtgpr2gpr : Thumb1pI<(outs GPR:$Rd), (ins tGPR:$Rm), AddrModeNone, - Size2Bytes, IIC_iMOVr, "mov", "\t$Rd, $Rm", "", []>, - T1Special<{1,0,?,0}> { - // A8.6.97 - bits<4> Rd; - bits<4> Rm; - // Bit {6} is encoded by the T1Special value. - let Inst{7} = Rd{3}; - let Inst{5-3} = Rm{2-0}; - let Inst{2-0} = Rd{2-0}; -} -def tMOVgpr2gpr : Thumb1pI<(outs GPR:$Rd), (ins GPR:$Rm), AddrModeNone, - Size2Bytes, IIC_iMOVr, "mov", "\t$Rd, $Rm", "", []>, - T1Special<{1,0,?,?}> { - // A8.6.97 - bits<4> Rd; - bits<4> Rm; - let Inst{7} = Rd{3}; - let Inst{6-3} = Rm; - let Inst{2-0} = Rd{2-0}; -} } // neverHasSideEffects // Multiply register diff --git a/lib/Target/ARM/Thumb1FrameLowering.cpp b/lib/Target/ARM/Thumb1FrameLowering.cpp index 326d4af..48211d8 100644 --- a/lib/Target/ARM/Thumb1FrameLowering.cpp +++ b/lib/Target/ARM/Thumb1FrameLowering.cpp @@ -160,7 +160,7 @@ void Thumb1FrameLowering::emitPrologue(MachineFunction &MF) const { // will be allocated after this, so we can still use the base pointer // to reference locals. if (RegInfo->hasBasePointer(MF)) - AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVgpr2gpr), BasePtr) + AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), BasePtr) .addReg(ARM::SP)); // If the frame has variable sized objects then the epilogue must restore @@ -240,11 +240,11 @@ void Thumb1FrameLowering::emitEpilogue(MachineFunction &MF, "No scratch register to restore SP from FP!"); emitThumbRegPlusImmediate(MBB, MBBI, dl, ARM::R4, FramePtr, -NumBytes, TII, *RegInfo); - AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVtgpr2gpr), + AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), ARM::SP) .addReg(ARM::R4)); } else - AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVtgpr2gpr), + AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), ARM::SP) .addReg(FramePtr)); } else { diff --git a/lib/Target/ARM/Thumb1InstrInfo.cpp b/lib/Target/ARM/Thumb1InstrInfo.cpp index 614ba81..218311d 100644 --- a/lib/Target/ARM/Thumb1InstrInfo.cpp +++ b/lib/Target/ARM/Thumb1InstrInfo.cpp @@ -36,17 +36,7 @@ void Thumb1InstrInfo::copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, DebugLoc DL, unsigned DestReg, unsigned SrcReg, bool KillSrc) const { - bool tDest = ARM::tGPRRegClass.contains(DestReg); - bool tSrc = ARM::tGPRRegClass.contains(SrcReg); - unsigned Opc = ARM::tMOVgpr2gpr; - if (tDest && tSrc) - Opc = ARM::tMOVr; - else if (tSrc) - Opc = ARM::tMOVtgpr2gpr; - else if (tDest) - Opc = ARM::tMOVgpr2tgpr; - - AddDefaultPred(BuildMI(MBB, I, DL, get(Opc), DestReg) + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::tMOVr), DestReg) .addReg(SrcReg, getKillRegState(KillSrc))); assert(ARM::GPRRegClass.contains(DestReg, SrcReg) && "Thumb1 can only copy GPR registers"); diff --git a/lib/Target/ARM/Thumb1RegisterInfo.cpp b/lib/Target/ARM/Thumb1RegisterInfo.cpp index 95fbe8c..4eb0b6c 100644 --- a/lib/Target/ARM/Thumb1RegisterInfo.cpp +++ b/lib/Target/ARM/Thumb1RegisterInfo.cpp @@ -417,7 +417,7 @@ rewriteFrameIndex(MachineBasicBlock::iterator II, unsigned FrameRegIdx, unsigned PredReg; if (Offset == 0 && getInstrPredicate(&MI, PredReg) == ARMCC::AL) { // Turn it into a move. - MI.setDesc(TII.get(ARM::tMOVgpr2tgpr)); + MI.setDesc(TII.get(ARM::tMOVr)); MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); // Remove offset and add predicate operands. MI.RemoveOperand(FrameRegIdx+1); @@ -564,7 +564,7 @@ Thumb1RegisterInfo::saveScavengerRegister(MachineBasicBlock &MBB, // the function, the offset will be negative. Use R12 instead since that's // a call clobbered register that we know won't be used in Thumb1 mode. DebugLoc DL; - AddDefaultPred(BuildMI(MBB, I, DL, TII.get(ARM::tMOVtgpr2gpr)) + AddDefaultPred(BuildMI(MBB, I, DL, TII.get(ARM::tMOVr)) .addReg(ARM::R12, RegState::Define) .addReg(Reg, RegState::Kill)); @@ -589,7 +589,7 @@ Thumb1RegisterInfo::saveScavengerRegister(MachineBasicBlock &MBB, } } // Restore the register from R12 - AddDefaultPred(BuildMI(MBB, UseMI, DL, TII.get(ARM::tMOVgpr2tgpr)). + AddDefaultPred(BuildMI(MBB, UseMI, DL, TII.get(ARM::tMOVr)). addReg(Reg, RegState::Define).addReg(ARM::R12, RegState::Kill)); return true; diff --git a/lib/Target/ARM/Thumb2ITBlockPass.cpp b/lib/Target/ARM/Thumb2ITBlockPass.cpp index 45e6937..360ec00 100644 --- a/lib/Target/ARM/Thumb2ITBlockPass.cpp +++ b/lib/Target/ARM/Thumb2ITBlockPass.cpp @@ -98,9 +98,6 @@ static bool isCopy(MachineInstr *MI) { case ARM::MOVr: case ARM::MOVr_TC: case ARM::tMOVr: - case ARM::tMOVgpr2tgpr: - case ARM::tMOVtgpr2gpr: - case ARM::tMOVgpr2gpr: case ARM::t2MOVr: return true; } diff --git a/lib/Target/ARM/Thumb2InstrInfo.cpp b/lib/Target/ARM/Thumb2InstrInfo.cpp index d958693..51b56aa 100644 --- a/lib/Target/ARM/Thumb2InstrInfo.cpp +++ b/lib/Target/ARM/Thumb2InstrInfo.cpp @@ -112,17 +112,7 @@ void Thumb2InstrInfo::copyPhysReg(MachineBasicBlock &MBB, if (!ARM::GPRRegClass.contains(DestReg, SrcReg)) return ARMBaseInstrInfo::copyPhysReg(MBB, I, DL, DestReg, SrcReg, KillSrc); - bool tDest = ARM::tGPRRegClass.contains(DestReg); - bool tSrc = ARM::tGPRRegClass.contains(SrcReg); - unsigned Opc = ARM::tMOVgpr2gpr; - if (tDest && tSrc) - Opc = ARM::tMOVr; - else if (tSrc) - Opc = ARM::tMOVtgpr2gpr; - else if (tDest) - Opc = ARM::tMOVgpr2tgpr; - - AddDefaultPred(BuildMI(MBB, I, DL, get(Opc), DestReg) + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::tMOVr), DestReg) .addReg(SrcReg, getKillRegState(KillSrc))); } @@ -231,7 +221,7 @@ void llvm::emitT2RegPlusImmediate(MachineBasicBlock &MBB, unsigned Opc = 0; if (DestReg == ARM::SP && BaseReg != ARM::SP) { // mov sp, rn. Note t2MOVr cannot be used. - AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVgpr2gpr),DestReg) + AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr),DestReg) .addReg(BaseReg).setMIFlags(MIFlags)); BaseReg = ARM::SP; continue; @@ -409,7 +399,7 @@ bool llvm::rewriteT2FrameIndex(MachineInstr &MI, unsigned FrameRegIdx, unsigned PredReg; if (Offset == 0 && getInstrPredicate(&MI, PredReg) == ARMCC::AL) { // Turn it into a move. - MI.setDesc(TII.get(ARM::tMOVgpr2gpr)); + MI.setDesc(TII.get(ARM::tMOVr)); MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); // Remove offset and remaining explicit predicate operands. do MI.RemoveOperand(FrameRegIdx+1); @@ -575,8 +565,7 @@ void Thumb2InstrInfo::scheduleTwoAddrSource(MachineInstr *SrcMI, MachineInstr *UseMI, const TargetRegisterInfo &TRI) const { - if (SrcMI->getOpcode() != ARM::tMOVgpr2gpr || - SrcMI->getOperand(1).isKill()) + if (SrcMI->getOpcode() != ARM::tMOVr || SrcMI->getOperand(1).isKill()) return; unsigned PredReg = 0; diff --git a/lib/Target/ARM/Thumb2SizeReduction.cpp b/lib/Target/ARM/Thumb2SizeReduction.cpp index cb44f8e..24a037c 100644 --- a/lib/Target/ARM/Thumb2SizeReduction.cpp +++ b/lib/Target/ARM/Thumb2SizeReduction.cpp @@ -82,7 +82,7 @@ namespace { { ARM::t2MOVi, ARM::tMOVi8, 0, 8, 0, 1, 0, 0,0, 0,0 }, { ARM::t2MOVi16,ARM::tMOVi8, 0, 8, 0, 1, 0, 0,0, 0,1 }, // FIXME: Do we need the 16-bit 'S' variant? - { ARM::t2MOVr,ARM::tMOVgpr2gpr,0, 0, 0, 0, 0, 1,0, 0,0 }, + { ARM::t2MOVr,ARM::tMOVr, 0, 0, 0, 0, 0, 1,0, 0,0 }, { ARM::t2MOVCCr,0, ARM::tMOVCCr, 0, 0, 0, 0, 0,1, 0,0 }, { ARM::t2MOVCCi,0, ARM::tMOVCCi, 0, 8, 0, 1, 0,1, 0,0 }, { ARM::t2MUL, 0, ARM::tMUL, 0, 0, 0, 1, 0,0, 1,0 }, -- cgit v1.1 From 098c7ac7c8bbc519a4ef4ab242140be459f0dae2 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Thu, 30 Jun 2011 23:42:18 +0000 Subject: Fix a problem with fast-isel return values introduced in r134018. We would put the return value from long double functions in the wrong register. This fixes gcc.c-torture/execute/conversion.c git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134205 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86FastISel.cpp | 5 +++-- test/CodeGen/X86/fp-stack-O0.ll | 24 ++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 test/CodeGen/X86/fp-stack-O0.ll diff --git a/lib/Target/X86/X86FastISel.cpp b/lib/Target/X86/X86FastISel.cpp index cdaa292..21e163a 100644 --- a/lib/Target/X86/X86FastISel.cpp +++ b/lib/Target/X86/X86FastISel.cpp @@ -1849,9 +1849,10 @@ bool X86FastISel::DoSelectCall(const Instruction *I, const char *MemIntName) { // out as F80 and use a truncate to move it from fp stack reg to xmm reg. if ((RVLocs[i].getLocReg() == X86::ST0 || RVLocs[i].getLocReg() == X86::ST1)) { - if (isScalarFPTypeInSSEReg(RVLocs[i].getValVT())) + if (isScalarFPTypeInSSEReg(RVLocs[i].getValVT())) { CopyVT = MVT::f80; - CopyReg = createResultReg(X86::RFP80RegisterClass); + CopyReg = createResultReg(X86::RFP80RegisterClass); + } BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(X86::FpPOP_RETVAL), CopyReg); } else { diff --git a/test/CodeGen/X86/fp-stack-O0.ll b/test/CodeGen/X86/fp-stack-O0.ll new file mode 100644 index 0000000..b9cb5d7 --- /dev/null +++ b/test/CodeGen/X86/fp-stack-O0.ll @@ -0,0 +1,24 @@ +; RUN: llc < %s -O0 | FileCheck %s +target triple = "x86_64-apple-macosx" + +declare x86_fp80 @x1(i32) nounwind +declare i32 @x2(x86_fp80, x86_fp80) nounwind + +; Keep track of the return value. +; CHECK: test1 +; CHECK: x1 +; Pass arguments on the stack. +; CHECK-NEXT: movq %rsp, [[RCX:%r..]] +; Copy constant-pool value. +; CHECK-NEXT: fldt LCPI +; CHECK-NEXT: fstpt 16([[RCX]]) +; Copy x1 return value. +; CHECK-NEXT: fstpt ([[RCX]]) +; CHECK-NEXT: x2 +define i32 @test1() nounwind uwtable ssp { +entry: + %call = call x86_fp80 (...)* bitcast (x86_fp80 (i32)* @x1 to x86_fp80 (...)*)(i32 -1) + %call1 = call i32 @x2(x86_fp80 %call, x86_fp80 0xK401EFFFFFFFF00000000) + ret i32 %call1 +} + -- cgit v1.1 From 2374cb8e7d05082e15e2ae9950bab87aa2c664c9 Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Thu, 30 Jun 2011 23:47:14 +0000 Subject: Use the correct registers on X86_64. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134208 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86RegisterInfo.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/Target/X86/X86RegisterInfo.cpp b/lib/Target/X86/X86RegisterInfo.cpp index 20f8992..d32b822 100644 --- a/lib/Target/X86/X86RegisterInfo.cpp +++ b/lib/Target/X86/X86RegisterInfo.cpp @@ -110,10 +110,10 @@ int X86RegisterInfo::getLLVMRegNum(unsigned DwarfRegNo, bool isEH) const { int X86RegisterInfo::getCompactUnwindRegNum(unsigned RegNum) const { switch (RegNum) { case X86::EBX: case X86::RBX: return 1; - case X86::ECX: case X86::RCX: return 2; - case X86::EDX: case X86::RDX: return 3; - case X86::EDI: case X86::RDI: return 4; - case X86::ESI: case X86::RSI: return 5; + case X86::ECX: case X86::R12: return 2; + case X86::EDX: case X86::R13: return 3; + case X86::EDI: case X86::R14: return 4; + case X86::ESI: case X86::R15: return 5; case X86::EBP: case X86::RBP: return 6; } -- cgit v1.1 From e08d4335ad29d74008222b4d7ac91c153ed66bec Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Thu, 30 Jun 2011 23:47:40 +0000 Subject: Improve comment: Show the register the DWARF label is added to. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134209 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/MC/MCDwarf.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp index 1a3596a..72ce441 100644 --- a/lib/MC/MCDwarf.cpp +++ b/lib/MC/MCDwarf.cpp @@ -621,7 +621,8 @@ void FrameEmitterImpl::EmitCFIInstruction(MCStreamer &Streamer, if (VerboseAsm) Streamer.AddComment(Twine("Offset ") + Twine(Offset)); Streamer.EmitSLEB128IntValue(Offset); } else if (Reg < 64) { - if (VerboseAsm) Streamer.AddComment("DW_CFA_offset"); + if (VerboseAsm) Streamer.AddComment(Twine("DW_CFA_offset + Reg(") + + Twine(Reg) + ")"); Streamer.EmitIntValue(dwarf::DW_CFA_offset + Reg, 1); if (VerboseAsm) Streamer.AddComment(Twine("Offset ") + Twine(Offset)); Streamer.EmitULEB128IntValue(Offset); -- cgit v1.1 From 35e6d4d6b6f975157beb1ff8c939fac6699d710c Mon Sep 17 00:00:00 2001 From: Eric Christopher Date: Thu, 30 Jun 2011 23:50:52 +0000 Subject: Rename Pair to RCPair lacking any better naming ideas. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134210 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMISelLowering.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index 1b9bcc9..09e1cc8 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -7528,8 +7528,8 @@ ARMTargetLowering::getSingleConstraintMatchWeight( return weight; } -typedef std::pair Pair; -Pair +typedef std::pair RCPair; +RCPair ARMTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const { if (Constraint.size() == 1) { @@ -7537,23 +7537,23 @@ ARMTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint, switch (Constraint[0]) { case 'l': // Low regs or general regs. if (Subtarget->isThumb()) - return Pair(0U, ARM::tGPRRegisterClass); + return RCPair(0U, ARM::tGPRRegisterClass); else - return Pair(0U, ARM::GPRRegisterClass); + return RCPair(0U, ARM::GPRRegisterClass); case 'h': // High regs or no regs. if (Subtarget->isThumb()) - return Pair(0U, ARM::hGPRRegisterClass); + return RCPair(0U, ARM::hGPRRegisterClass); else - return Pair(0u, static_cast(0)); + return RCPair(0u, static_cast(0)); case 'r': - return Pair(0U, ARM::GPRRegisterClass); + return RCPair(0U, ARM::GPRRegisterClass); case 'w': if (VT == MVT::f32) - return Pair(0U, ARM::SPRRegisterClass); + return RCPair(0U, ARM::SPRRegisterClass); if (VT.getSizeInBits() == 64) - return Pair(0U, ARM::DPRRegisterClass); + return RCPair(0U, ARM::DPRRegisterClass); if (VT.getSizeInBits() == 128) - return Pair(0U, ARM::QPRRegisterClass); + return RCPair(0U, ARM::QPRRegisterClass); break; } } -- cgit v1.1 From 09b4467ac556e82ba5ff368b035d38697d8459da Mon Sep 17 00:00:00 2001 From: Eric Christopher Date: Thu, 30 Jun 2011 23:59:16 +0000 Subject: Capitalize the unsigned part of the initializer. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134211 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMISelLowering.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index 09e1cc8..7828447 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -7544,7 +7544,7 @@ ARMTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint, if (Subtarget->isThumb()) return RCPair(0U, ARM::hGPRRegisterClass); else - return RCPair(0u, static_cast(0)); + return RCPair(0U, static_cast(0)); case 'r': return RCPair(0U, ARM::GPRRegisterClass); case 'w': -- cgit v1.1 From c3882164cbf794dbe21816a2946a31bc9e02a419 Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Thu, 30 Jun 2011 23:59:38 +0000 Subject: Remove tabs. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134212 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/MC/MCDwarf.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp index 72ce441..13164ed 100644 --- a/lib/MC/MCDwarf.cpp +++ b/lib/MC/MCDwarf.cpp @@ -30,23 +30,23 @@ using namespace llvm; #define SPECIAL_ADDR(op) (((op) - DWARF2_LINE_OPCODE_BASE)/DWARF2_LINE_RANGE) // The maximum address skip amount that can be encoded with a special op. -#define MAX_SPECIAL_ADDR_DELTA SPECIAL_ADDR(255) +#define MAX_SPECIAL_ADDR_DELTA SPECIAL_ADDR(255) // First special line opcode - leave room for the standard opcodes. // Note: If you want to change this, you'll have to update the // "standard_opcode_lengths" table that is emitted in DwarfFileTable::Emit(). -#define DWARF2_LINE_OPCODE_BASE 13 +#define DWARF2_LINE_OPCODE_BASE 13 // Minimum line offset in a special line info. opcode. This value // was chosen to give a reasonable range of values. -#define DWARF2_LINE_BASE -5 +#define DWARF2_LINE_BASE -5 // Range of line offsets in a special line info. opcode. -# define DWARF2_LINE_RANGE 14 +#define DWARF2_LINE_RANGE 14 // Define the architecture-dependent minimum instruction length (in bytes). // This value should be rather too small than too big. -# define DWARF2_LINE_MIN_INSN_LENGTH 1 +#define DWARF2_LINE_MIN_INSN_LENGTH 1 // Note: when DWARF2_LINE_MIN_INSN_LENGTH == 1 which is the current setting, // this routine is a nop and will be optimized away. @@ -290,7 +290,7 @@ void MCDwarfFileTable::Emit(MCStreamer *MCOS) { const std::vector &MCLineSectionOrder = MCOS->getContext().getMCLineSectionOrder(); for (std::vector::const_iterator it = - MCLineSectionOrder.begin(), ie = MCLineSectionOrder.end(); it != ie; + MCLineSectionOrder.begin(), ie = MCLineSectionOrder.end(); it != ie; ++it) { const MCSection *Sec = *it; const MCLineSection *Line = MCLineSections.lookup(Sec); -- cgit v1.1 From 89bd71fc53fc95f2526e07ec338a8c998e9ead8d Mon Sep 17 00:00:00 2001 From: Eric Christopher Date: Fri, 1 Jul 2011 00:14:47 +0000 Subject: Add support for the 'x' constraint. Part of rdar://9307836 and rdar://9119939 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134215 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMISelLowering.cpp | 9 +++++++++ test/CodeGen/ARM/inlineasm3.ll | 10 ++++++++++ 2 files changed, 19 insertions(+) diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index 7828447..22cd78f 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -7483,6 +7483,7 @@ ARMTargetLowering::getConstraintType(const std::string &Constraint) const { case 'l': return C_RegisterClass; case 'w': return C_RegisterClass; case 'h': return C_RegisterClass; + case 'x': return C_RegisterClass; } } else if (Constraint.size() == 2) { switch (Constraint[0]) { @@ -7555,6 +7556,14 @@ ARMTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint, if (VT.getSizeInBits() == 128) return RCPair(0U, ARM::QPRRegisterClass); break; + case 'x': + if (VT == MVT::f32) + return RCPair(0U, ARM::SPR_8RegisterClass); + if (VT.getSizeInBits() == 64) + return RCPair(0U, ARM::DPR_8RegisterClass); + if (VT.getSizeInBits() == 128) + return RCPair(0U, ARM::QPR_8RegisterClass); + break; } } if (StringRef("{cc}").equals_lower(Constraint)) diff --git a/test/CodeGen/ARM/inlineasm3.ll b/test/CodeGen/ARM/inlineasm3.ll index 58687b9..f09deb3 100644 --- a/test/CodeGen/ARM/inlineasm3.ll +++ b/test/CodeGen/ARM/inlineasm3.ll @@ -58,3 +58,13 @@ entry: call void asm sideeffect "flds s15, $0 \0A", "*^Uvm,~{s15}"(float* @k.2126) nounwind ret i32 0 } + +; Radar 9307836 & 9119939 + +define float @t6(float %y) nounwind { +entry: +; CHECK: t6 +; CHECK: flds s15, s0 + %0 = tail call float asm "flds s15, $0", "=x"() nounwind + ret float %0 +} -- cgit v1.1 From 0c13e9471a4aa32207923d84c0990eeb9bb898ab Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Fri, 1 Jul 2011 00:16:54 +0000 Subject: Add 134199 back, but disable the optimization when the second copy is a kill. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134216 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/RegisterCoalescer.cpp | 110 ++++++++++++++++++++++++++++++++++---- 1 file changed, 100 insertions(+), 10 deletions(-) diff --git a/lib/CodeGen/RegisterCoalescer.cpp b/lib/CodeGen/RegisterCoalescer.cpp index 3b8a3e8..57156cb 100644 --- a/lib/CodeGen/RegisterCoalescer.cpp +++ b/lib/CodeGen/RegisterCoalescer.cpp @@ -1187,6 +1187,70 @@ static unsigned ComputeUltimateVN(VNInfo *VNI, return ThisValNoAssignments[VN] = UltimateVN; } + +// Find out if we have something like +// A = X +// B = X +// if so, we can pretend this is actually +// A = X +// B = A +// which allows us to coalesce A and B. +// MI is the definition of B. LR is the life range of A that includes +// the slot just before B. If we return true, we add "B = X" to DupCopies. +static bool RegistersDefinedFromSameValue(const TargetRegisterInfo &tri, + CoalescerPair &CP, MachineInstr *MI, + LiveRange *LR, + SmallVector &DupCopies) { + // FIXME: This is very conservative. For example, we don't handle + // physical registers. + + if (!MI->isFullCopy() || CP.isPartial() || CP.isPhys()) + return false; + + // FIXME: If "B = X" kills X, we have to move the kill back to its + // previous use. For now we just avoid the optimization in that case. + if (MI->getOperand(1).isKill()) + return false; + + unsigned Dst = MI->getOperand(0).getReg(); + unsigned Src = MI->getOperand(1).getReg(); + + if (!TargetRegisterInfo::isVirtualRegister(Src) || + !TargetRegisterInfo::isVirtualRegister(Dst)) + return false; + + unsigned A = CP.getDstReg(); + unsigned B = CP.getSrcReg(); + + if (B == Dst) + std::swap(A, B); + assert(Dst == A); + + VNInfo *Other = LR->valno; + if (!Other->isDefByCopy()) + return false; + const MachineInstr *OtherMI = Other->getCopy(); + + if (!OtherMI->isFullCopy()) + return false; + + unsigned OtherDst = OtherMI->getOperand(0).getReg(); + unsigned OtherSrc = OtherMI->getOperand(1).getReg(); + + if (!TargetRegisterInfo::isVirtualRegister(OtherSrc) || + !TargetRegisterInfo::isVirtualRegister(OtherDst)) + return false; + + assert(OtherDst == B); + + if (Src != OtherSrc) + return false; + + DupCopies.push_back(MI); + + return true; +} + /// JoinIntervals - Attempt to join these two intervals. On failure, this /// returns false. bool RegisterCoalescer::JoinIntervals(CoalescerPair &CP) { @@ -1242,6 +1306,8 @@ bool RegisterCoalescer::JoinIntervals(CoalescerPair &CP) { DenseMap RHSValsDefinedFromLHS; SmallVector NewVNInfo; + SmallVector DupCopies; + LiveInterval &LHS = li_->getOrCreateInterval(CP.getDstReg()); DEBUG({ dbgs() << "\t\tLHS = "; LHS.print(dbgs(), tri_); dbgs() << "\n"; }); @@ -1257,15 +1323,18 @@ bool RegisterCoalescer::JoinIntervals(CoalescerPair &CP) { if (VNI->hasRedefByEC()) return false; - // DstReg is known to be a register in the LHS interval. If the src is - // from the RHS interval, we can use its value #. - if (!CP.isCoalescable(VNI->getCopy())) - continue; - // Figure out the value # from the RHS. LiveRange *lr = RHS.getLiveRangeContaining(VNI->def.getPrevSlot()); // The copy could be to an aliased physreg. if (!lr) continue; + + // DstReg is known to be a register in the LHS interval. If the src is + // from the RHS interval, we can use its value #. + MachineInstr *MI = VNI->getCopy(); + if (!CP.isCoalescable(MI) && + !RegistersDefinedFromSameValue(*tri_, CP, MI, lr, DupCopies)) + continue; + LHSValsDefinedFromRHS[VNI] = lr->valno; } @@ -1281,15 +1350,18 @@ bool RegisterCoalescer::JoinIntervals(CoalescerPair &CP) { if (VNI->hasRedefByEC()) return false; - // DstReg is known to be a register in the RHS interval. If the src is - // from the LHS interval, we can use its value #. - if (!CP.isCoalescable(VNI->getCopy())) - continue; - // Figure out the value # from the LHS. LiveRange *lr = LHS.getLiveRangeContaining(VNI->def.getPrevSlot()); // The copy could be to an aliased physreg. if (!lr) continue; + + // DstReg is known to be a register in the RHS interval. If the src is + // from the LHS interval, we can use its value #. + MachineInstr *MI = VNI->getCopy(); + if (!CP.isCoalescable(MI) && + !RegistersDefinedFromSameValue(*tri_, CP, MI, lr, DupCopies)) + continue; + RHSValsDefinedFromLHS[VNI] = lr->valno; } @@ -1394,6 +1466,24 @@ bool RegisterCoalescer::JoinIntervals(CoalescerPair &CP) { if (RHSValNoAssignments.empty()) RHSValNoAssignments.push_back(-1); + for (SmallVector::iterator I = DupCopies.begin(), + E = DupCopies.end(); I != E; ++I) { + MachineInstr *MI = *I; + + // We have pretended that the assignment to B in + // A = X + // B = X + // was actually a copy from A. Now that we decided to coalesce A and B, + // transform the code into + // A = X + // X = X + // and mark the X as coalesced to keep the illusion. + unsigned Src = MI->getOperand(1).getReg(); + MI->getOperand(0).substVirtReg(Src, 0, *tri_); + + markAsJoined(MI); + } + // If we get here, we know that we can coalesce the live ranges. Ask the // intervals to coalesce themselves now. LHS.join(RHS, &LHSValNoAssignments[0], &RHSValNoAssignments[0], NewVNInfo, -- cgit v1.1 From 1070f82569be2602640e15e3a0a3eda55228b8aa Mon Sep 17 00:00:00 2001 From: Eric Christopher Date: Fri, 1 Jul 2011 00:19:27 +0000 Subject: We'll return a null RC by default if we can't match. Part of rdar://9119939 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134217 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMISelLowering.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index 22cd78f..1141f42 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -7544,8 +7544,7 @@ ARMTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint, case 'h': // High regs or no regs. if (Subtarget->isThumb()) return RCPair(0U, ARM::hGPRRegisterClass); - else - return RCPair(0U, static_cast(0)); + break; case 'r': return RCPair(0U, ARM::GPRRegisterClass); case 'w': -- cgit v1.1 From e1bff38386b0af24b5564c3d20888c7bbb045099 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Fri, 1 Jul 2011 00:23:10 +0000 Subject: Switch SubtargetFeatures from std::string to StringRef. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134219 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/MC/SubtargetFeature.h | 13 ++++++------ lib/MC/SubtargetFeature.cpp | 41 ++++++++++++++++++-------------------- 2 files changed, 25 insertions(+), 29 deletions(-) diff --git a/include/llvm/MC/SubtargetFeature.h b/include/llvm/MC/SubtargetFeature.h index b2d7fb5..ff726ec 100644 --- a/include/llvm/MC/SubtargetFeature.h +++ b/include/llvm/MC/SubtargetFeature.h @@ -18,13 +18,13 @@ #ifndef LLVM_MC_SUBTARGETFEATURE_H #define LLVM_MC_SUBTARGETFEATURE_H -#include #include #include "llvm/ADT/Triple.h" #include "llvm/Support/DataTypes.h" namespace llvm { class raw_ostream; + class StringRef; //===----------------------------------------------------------------------===// /// @@ -74,24 +74,23 @@ struct SubtargetInfoKV { class SubtargetFeatures { std::vector Features; // Subtarget features as a vector public: - explicit SubtargetFeatures(const std::string &Initial = std::string()); + explicit SubtargetFeatures(const StringRef Initial = ""); /// Features string accessors. - std::string getString() const; - void setString(const std::string &Initial); + StringRef getString() const; /// Adding Features. - void AddFeature(const std::string &String, bool IsEnabled = true); + void AddFeature(const StringRef String, bool IsEnabled = true); /// Get feature bits of a CPU. - uint64_t getFeatureBits(const std::string &CPU, + uint64_t getFeatureBits(const StringRef CPU, const SubtargetFeatureKV *CPUTable, size_t CPUTableSize, const SubtargetFeatureKV *FeatureTable, size_t FeatureTableSize); /// Get scheduling itinerary of a CPU. - void *getItinerary(const std::string &CPU, + void *getItinerary(const StringRef CPU, const SubtargetInfoKV *Table, size_t TableSize); /// Print feature string. diff --git a/lib/MC/SubtargetFeature.cpp b/lib/MC/SubtargetFeature.cpp index a6f6b13..247f73a 100644 --- a/lib/MC/SubtargetFeature.cpp +++ b/lib/MC/SubtargetFeature.cpp @@ -27,7 +27,7 @@ using namespace llvm; /// hasFlag - Determine if a feature has a flag; '+' or '-' /// -static inline bool hasFlag(const std::string &Feature) { +static inline bool hasFlag(const StringRef Feature) { assert(!Feature.empty() && "Empty string"); // Get first character char Ch = Feature[0]; @@ -37,13 +37,13 @@ static inline bool hasFlag(const std::string &Feature) { /// StripFlag - Return string stripped of flag. /// -static inline std::string StripFlag(const std::string &Feature) { +static inline std::string StripFlag(const StringRef Feature) { return hasFlag(Feature) ? Feature.substr(1) : Feature; } /// isEnabled - Return true if enable flag; '+'. /// -static inline bool isEnabled(const std::string &Feature) { +static inline bool isEnabled(const StringRef Feature) { assert(!Feature.empty() && "Empty string"); // Get first character char Ch = Feature[0]; @@ -53,16 +53,19 @@ static inline bool isEnabled(const std::string &Feature) { /// PrependFlag - Return a string with a prepended flag; '+' or '-'. /// -static inline std::string PrependFlag(const std::string &Feature, - bool IsEnabled) { +static inline StringRef PrependFlag(const StringRef Feature, + bool IsEnabled) { assert(!Feature.empty() && "Empty string"); - if (hasFlag(Feature)) return Feature; - return std::string(IsEnabled ? "+" : "-") + Feature; + if (hasFlag(Feature)) + return Feature; + std::string Prefix = IsEnabled ? "+" : "-"; + Prefix += Feature; + return StringRef(Prefix); } /// Split - Splits a string of comma separated items in to a vector of strings. /// -static void Split(std::vector &V, const std::string &S) { +static void Split(std::vector &V, const StringRef S) { if (S.empty()) return; @@ -106,7 +109,7 @@ static std::string Join(const std::vector &V) { } /// Adding features. -void SubtargetFeatures::AddFeature(const std::string &String, +void SubtargetFeatures::AddFeature(const StringRef String, bool IsEnabled) { // Don't add empty features if (!String.empty()) { @@ -116,10 +119,10 @@ void SubtargetFeatures::AddFeature(const std::string &String, } /// Find KV in array using binary search. -template const T *Find(const std::string &S, const T *A, size_t L) { +template const T *Find(const StringRef S, const T *A, size_t L) { // Make the lower bound element we're looking for T KV; - KV.Key = S.c_str(); + KV.Key = S.data(); // Determine the end of the array const T *Hi = A + L; // Binary search the array @@ -173,21 +176,15 @@ static void Help(const SubtargetFeatureKV *CPUTable, size_t CPUTableSize, // SubtargetFeatures Implementation //===----------------------------------------------------------------------===// -SubtargetFeatures::SubtargetFeatures(const std::string &Initial) { +SubtargetFeatures::SubtargetFeatures(const StringRef Initial) { // Break up string into separate features Split(Features, Initial); } -std::string SubtargetFeatures::getString() const { +StringRef SubtargetFeatures::getString() const { return Join(Features); } -void SubtargetFeatures::setString(const std::string &Initial) { - // Throw out old features - Features.clear(); - // Break up string into separate features - Split(Features, LowercaseString(Initial)); -} /// SetImpliedBits - For each feature that is (transitively) implied by this /// feature, set it. @@ -229,7 +226,7 @@ void ClearImpliedBits(uint64_t &Bits, const SubtargetFeatureKV *FeatureEntry, /// getFeatureBits - Get feature bits a CPU. /// -uint64_t SubtargetFeatures::getFeatureBits(const std::string &CPU, +uint64_t SubtargetFeatures::getFeatureBits(const StringRef CPU, const SubtargetFeatureKV *CPUTable, size_t CPUTableSize, const SubtargetFeatureKV *FeatureTable, @@ -272,7 +269,7 @@ uint64_t SubtargetFeatures::getFeatureBits(const std::string &CPU, } // Iterate through each feature for (size_t i = 0, E = Features.size(); i < E; i++) { - const std::string &Feature = Features[i]; + const StringRef Feature = Features[i]; // Check for help if (Feature == "+help") @@ -306,7 +303,7 @@ uint64_t SubtargetFeatures::getFeatureBits(const std::string &CPU, } /// Get scheduling itinerary of a CPU. -void *SubtargetFeatures::getItinerary(const std::string &CPU, +void *SubtargetFeatures::getItinerary(const StringRef CPU, const SubtargetInfoKV *Table, size_t TableSize) { assert(Table && "missing table"); -- cgit v1.1 From d5dc9eca2beece0faa85e7cbf17182fe7fcd0b36 Mon Sep 17 00:00:00 2001 From: Eric Christopher Date: Fri, 1 Jul 2011 00:30:46 +0000 Subject: Add support for the ARM 't' register constraint. And another testcase for the 'x' register constraint. Part of rdar://9119939 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134220 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMISelLowering.cpp | 5 +++++ test/CodeGen/ARM/inlineasm3.ll | 20 ++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index 1141f42..4a78ad4 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -7484,6 +7484,7 @@ ARMTargetLowering::getConstraintType(const std::string &Constraint) const { case 'w': return C_RegisterClass; case 'h': return C_RegisterClass; case 'x': return C_RegisterClass; + case 't': return C_RegisterClass; } } else if (Constraint.size() == 2) { switch (Constraint[0]) { @@ -7563,6 +7564,10 @@ ARMTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint, if (VT.getSizeInBits() == 128) return RCPair(0U, ARM::QPR_8RegisterClass); break; + case 't': + if (VT == MVT::f32) + return RCPair(0U, ARM::SPRRegisterClass); + break; } } if (StringRef("{cc}").equals_lower(Constraint)) diff --git a/test/CodeGen/ARM/inlineasm3.ll b/test/CodeGen/ARM/inlineasm3.ll index f09deb3..00257e1 100644 --- a/test/CodeGen/ARM/inlineasm3.ll +++ b/test/CodeGen/ARM/inlineasm3.ll @@ -68,3 +68,23 @@ entry: %0 = tail call float asm "flds s15, $0", "=x"() nounwind ret float %0 } + +; Radar 9307836 & 9119939 + +define double @t7(double %y) nounwind ssp { +entry: +; CHECK: t7 +; CHECK: flds s15, d0 + %0 = tail call double asm "flds s15, $0", "=x"() nounwind + ret double %0 +} + +; Radar 9307836 & 9119939 + +define float @t8(float %y) nounwind ssp { +entry: +; CHECK: t8 +; CHECK: flds s15, s0 + %0 = tail call float asm "flds s15, $0", "=t"() nounwind + ret float %0 +} -- cgit v1.1 From 30cb6dda5ae441f27edef302cbb33936fbafba6d Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 1 Jul 2011 00:42:17 +0000 Subject: Improve constant folding of undef for binary operators. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134221 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/VMCore/ConstantFold.cpp | 28 ++++++++-- test/Transforms/InstSimplify/binop.ll | 99 +++++++++++++++++++++++++++++++++++ 2 files changed, 123 insertions(+), 4 deletions(-) create mode 100644 test/Transforms/InstSimplify/binop.ll diff --git a/lib/VMCore/ConstantFold.cpp b/lib/VMCore/ConstantFold.cpp index 579d356..8cca06f 100644 --- a/lib/VMCore/ConstantFold.cpp +++ b/lib/VMCore/ConstantFold.cpp @@ -1014,20 +1014,38 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode, case Instruction::Add: case Instruction::Sub: return UndefValue::get(C1->getType()); - case Instruction::Mul: case Instruction::And: + if (isa(C1) && isa(C2)) // undef & undef -> undef + return C1; + return Constant::getNullValue(C1->getType()); // undef & X -> 0 + case Instruction::Mul: { + ConstantInt *CI; + // X * undef -> undef if X is odd or undef + if (((CI = dyn_cast(C1)) && CI->getValue()[0]) || + ((CI = dyn_cast(C2)) && CI->getValue()[0]) || + (isa(C1) && isa(C2))) + return UndefValue::get(C1->getType()); + + // X * undef -> 0 otherwise return Constant::getNullValue(C1->getType()); + } case Instruction::UDiv: case Instruction::SDiv: + // undef / 1 -> undef + if (Opcode == Instruction::UDiv || Opcode == Instruction::SDiv) + if (ConstantInt *CI2 = dyn_cast(C2)) + if (CI2->isOne()) + return C1; + // FALL THROUGH case Instruction::URem: case Instruction::SRem: if (!isa(C2)) // undef / X -> 0 return Constant::getNullValue(C1->getType()); return C2; // X / undef -> undef case Instruction::Or: // X | undef -> -1 - if (const VectorType *PTy = dyn_cast(C1->getType())) - return Constant::getAllOnesValue(PTy); - return Constant::getAllOnesValue(C1->getType()); + if (isa(C1) && isa(C2)) // undef | undef -> undef + return C1; + return Constant::getAllOnesValue(C1->getType()); // undef | X -> ~0 case Instruction::LShr: if (isa(C2) && isa(C1)) return C1; // undef lshr undef -> undef @@ -1041,6 +1059,8 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode, else return C1; // X ashr undef --> X case Instruction::Shl: + if (isa(C2) && isa(C1)) + return C1; // undef shl undef -> undef // undef << X -> 0 or X << undef -> 0 return Constant::getNullValue(C1->getType()); } diff --git a/test/Transforms/InstSimplify/binop.ll b/test/Transforms/InstSimplify/binop.ll new file mode 100644 index 0000000..f4bc557 --- /dev/null +++ b/test/Transforms/InstSimplify/binop.ll @@ -0,0 +1,99 @@ +; RUN: opt -instsimplify -S < %s | FileCheck %s + +; @test0 +; CHECK: ret i64 undef +define i64 @test0() { + %r = mul i64 undef, undef + ret i64 %r +} + +; @test1 +; CHECK: ret i64 undef +define i64 @test1() { + %r = mul i64 3, undef + ret i64 %r +} + +; @test2 +; CHECK: ret i64 undef +define i64 @test2() { + %r = mul i64 undef, 3 + ret i64 %r +} + +; @test3 +; CHECK: ret i64 0 +define i64 @test3() { + %r = mul i64 undef, 6 + ret i64 %r +} + +; @test4 +; CHECK: ret i64 0 +define i64 @test4() { + %r = mul i64 6, undef + ret i64 %r +} + +; @test5 +; CHECK: ret i64 undef +define i64 @test5() { + %r = and i64 undef, undef + ret i64 %r +} + +; @test6 +; CHECK: ret i64 undef +define i64 @test6() { + %r = or i64 undef, undef + ret i64 %r +} + +; @test7 +; CHECK: ret i64 undef +define i64 @test7() { + %r = udiv i64 undef, 1 + ret i64 %r +} + +; @test8 +; CHECK: ret i64 undef +define i64 @test8() { + %r = sdiv i64 undef, 1 + ret i64 %r +} + +; @test9 +; CHECK: ret i64 0 +define i64 @test9() { + %r = urem i64 undef, 1 + ret i64 %r +} + +; @test10 +; CHECK: ret i64 0 +define i64 @test10() { + %r = srem i64 undef, 1 + ret i64 %r +} + +; @test11 +; CHECK: ret i64 undef +define i64 @test11() { + %r = shl i64 undef, undef + ret i64 %r +} + +; @test12 +; CHECK: ret i64 undef +define i64 @test12() { + %r = ashr i64 undef, undef + ret i64 %r +} + +; @test13 +; CHECK: ret i64 undef +define i64 @test13() { + %r = lshr i64 undef, undef + ret i64 %r +} -- cgit v1.1 From 5e653c925c7da969c3fb5fa9a46263ffb160b81e Mon Sep 17 00:00:00 2001 From: Eric Christopher Date: Fri, 1 Jul 2011 01:00:07 +0000 Subject: Add support for the 'j' immediate constraint. This is conditionalized on supporting the instruction that the constraint is for 'movw'. Part of rdar://9119939 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134222 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMISelLowering.cpp | 9 +++++++++ test/CodeGen/ARM/inlineasm3.ll | 16 +++++++++++++--- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index 4a78ad4..fb738cd 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -7485,6 +7485,7 @@ ARMTargetLowering::getConstraintType(const std::string &Constraint) const { case 'h': return C_RegisterClass; case 'x': return C_RegisterClass; case 't': return C_RegisterClass; + case 'j': return C_Other; // Constant for movw. } } else if (Constraint.size() == 2) { switch (Constraint[0]) { @@ -7590,6 +7591,7 @@ void ARMTargetLowering::LowerAsmOperandForConstraint(SDValue Op, char ConstraintLetter = Constraint[0]; switch (ConstraintLetter) { default: break; + case 'j': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': ConstantSDNode *C = dyn_cast(Op); @@ -7604,6 +7606,13 @@ void ARMTargetLowering::LowerAsmOperandForConstraint(SDValue Op, return; switch (ConstraintLetter) { + case 'j': + // Constant suitable for movw, must be between 0 and + // 65535. + if (Subtarget->hasV6T2Ops()) + if (CVal >= 0 && CVal <= 65535) + break; + return; case 'I': if (Subtarget->isThumb1Only()) { // This must be a constant between 0 and 255, for ADD diff --git a/test/CodeGen/ARM/inlineasm3.ll b/test/CodeGen/ARM/inlineasm3.ll index 00257e1..853585d 100644 --- a/test/CodeGen/ARM/inlineasm3.ll +++ b/test/CodeGen/ARM/inlineasm3.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -march=arm -mattr=+neon | FileCheck %s +; RUN: llc < %s -march=arm -mattr=+neon,+v6t2 | FileCheck %s ; Radar 7449043 %struct.int32x4_t = type { <4 x i32> } @@ -71,7 +71,7 @@ entry: ; Radar 9307836 & 9119939 -define double @t7(double %y) nounwind ssp { +define double @t7(double %y) nounwind { entry: ; CHECK: t7 ; CHECK: flds s15, d0 @@ -81,10 +81,20 @@ entry: ; Radar 9307836 & 9119939 -define float @t8(float %y) nounwind ssp { +define float @t8(float %y) nounwind { entry: ; CHECK: t8 ; CHECK: flds s15, s0 %0 = tail call float asm "flds s15, $0", "=t"() nounwind ret float %0 } + +; Radar 9307836 & 9119939 + +define i32 @t9(i32 %r0) nounwind { +entry: +; CHECK: t9 +; CHECK: movw r0, #27182 + %0 = tail call i32 asm "movw $0, $1", "=r,j"(i32 27182) nounwind + ret i32 %0 +} -- cgit v1.1 From 68c0dbc14fb7599987fb3e27be4e12c1ac36535e Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 1 Jul 2011 01:03:43 +0000 Subject: Improve constant folding of undef for cmp and select operators. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134223 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/InstructionSimplify.cpp | 8 +-- lib/VMCore/ConstantFold.cpp | 9 ++- test/Transforms/InstSimplify/binop.ll | 99 -------------------------- test/Transforms/InstSimplify/undef.ll | 127 ++++++++++++++++++++++++++++++++++ 4 files changed, 138 insertions(+), 105 deletions(-) delete mode 100644 test/Transforms/InstSimplify/binop.ll create mode 100644 test/Transforms/InstSimplify/undef.ll diff --git a/lib/Analysis/InstructionSimplify.cpp b/lib/Analysis/InstructionSimplify.cpp index 9d78f8b..8709f6b 100644 --- a/lib/Analysis/InstructionSimplify.cpp +++ b/lib/Analysis/InstructionSimplify.cpp @@ -2204,15 +2204,15 @@ Value *llvm::SimplifySelectInst(Value *CondVal, Value *TrueVal, Value *FalseVal, if (TrueVal == FalseVal) return TrueVal; - if (isa(TrueVal)) // select C, undef, X -> X - return FalseVal; - if (isa(FalseVal)) // select C, X, undef -> X - return TrueVal; if (isa(CondVal)) { // select undef, X, Y -> X or Y if (isa(TrueVal)) return TrueVal; return FalseVal; } + if (isa(TrueVal)) // select C, undef, X -> X + return FalseVal; + if (isa(FalseVal)) // select C, X, undef -> X + return TrueVal; return 0; } diff --git a/lib/VMCore/ConstantFold.cpp b/lib/VMCore/ConstantFold.cpp index 8cca06f..b7a1350 100644 --- a/lib/VMCore/ConstantFold.cpp +++ b/lib/VMCore/ConstantFold.cpp @@ -730,9 +730,12 @@ Constant *llvm::ConstantFoldSelectInstruction(Constant *Cond, } + if (isa(Cond)) { + if (isa(V1)) return V1; + return V2; + } if (isa(V1)) return V2; if (isa(V2)) return V1; - if (isa(Cond)) return V1; if (V1 == V2) return V1; if (ConstantExpr *TrueVal = dyn_cast(V1)) { @@ -1851,7 +1854,9 @@ Constant *llvm::ConstantFoldCompareInstruction(unsigned short pred, if (isa(C1) || isa(C2)) { // For EQ and NE, we can always pick a value for the undef to make the // predicate pass or fail, so we can return undef. - if (ICmpInst::isEquality(ICmpInst::Predicate(pred))) + // Also, if both operands are undef, we can return undef. + if (ICmpInst::isEquality(ICmpInst::Predicate(pred)) || + (isa(C1) && isa(C2))) return UndefValue::get(ResultTy); // Otherwise, pick the same value as the non-undef operand, and fold // it to true or false. diff --git a/test/Transforms/InstSimplify/binop.ll b/test/Transforms/InstSimplify/binop.ll deleted file mode 100644 index f4bc557..0000000 --- a/test/Transforms/InstSimplify/binop.ll +++ /dev/null @@ -1,99 +0,0 @@ -; RUN: opt -instsimplify -S < %s | FileCheck %s - -; @test0 -; CHECK: ret i64 undef -define i64 @test0() { - %r = mul i64 undef, undef - ret i64 %r -} - -; @test1 -; CHECK: ret i64 undef -define i64 @test1() { - %r = mul i64 3, undef - ret i64 %r -} - -; @test2 -; CHECK: ret i64 undef -define i64 @test2() { - %r = mul i64 undef, 3 - ret i64 %r -} - -; @test3 -; CHECK: ret i64 0 -define i64 @test3() { - %r = mul i64 undef, 6 - ret i64 %r -} - -; @test4 -; CHECK: ret i64 0 -define i64 @test4() { - %r = mul i64 6, undef - ret i64 %r -} - -; @test5 -; CHECK: ret i64 undef -define i64 @test5() { - %r = and i64 undef, undef - ret i64 %r -} - -; @test6 -; CHECK: ret i64 undef -define i64 @test6() { - %r = or i64 undef, undef - ret i64 %r -} - -; @test7 -; CHECK: ret i64 undef -define i64 @test7() { - %r = udiv i64 undef, 1 - ret i64 %r -} - -; @test8 -; CHECK: ret i64 undef -define i64 @test8() { - %r = sdiv i64 undef, 1 - ret i64 %r -} - -; @test9 -; CHECK: ret i64 0 -define i64 @test9() { - %r = urem i64 undef, 1 - ret i64 %r -} - -; @test10 -; CHECK: ret i64 0 -define i64 @test10() { - %r = srem i64 undef, 1 - ret i64 %r -} - -; @test11 -; CHECK: ret i64 undef -define i64 @test11() { - %r = shl i64 undef, undef - ret i64 %r -} - -; @test12 -; CHECK: ret i64 undef -define i64 @test12() { - %r = ashr i64 undef, undef - ret i64 %r -} - -; @test13 -; CHECK: ret i64 undef -define i64 @test13() { - %r = lshr i64 undef, undef - ret i64 %r -} diff --git a/test/Transforms/InstSimplify/undef.ll b/test/Transforms/InstSimplify/undef.ll new file mode 100644 index 0000000..8134cc8 --- /dev/null +++ b/test/Transforms/InstSimplify/undef.ll @@ -0,0 +1,127 @@ +; RUN: opt -instsimplify -S < %s | FileCheck %s + +; @test0 +; CHECK: ret i64 undef +define i64 @test0() { + %r = mul i64 undef, undef + ret i64 %r +} + +; @test1 +; CHECK: ret i64 undef +define i64 @test1() { + %r = mul i64 3, undef + ret i64 %r +} + +; @test2 +; CHECK: ret i64 undef +define i64 @test2() { + %r = mul i64 undef, 3 + ret i64 %r +} + +; @test3 +; CHECK: ret i64 0 +define i64 @test3() { + %r = mul i64 undef, 6 + ret i64 %r +} + +; @test4 +; CHECK: ret i64 0 +define i64 @test4() { + %r = mul i64 6, undef + ret i64 %r +} + +; @test5 +; CHECK: ret i64 undef +define i64 @test5() { + %r = and i64 undef, undef + ret i64 %r +} + +; @test6 +; CHECK: ret i64 undef +define i64 @test6() { + %r = or i64 undef, undef + ret i64 %r +} + +; @test7 +; CHECK: ret i64 undef +define i64 @test7() { + %r = udiv i64 undef, 1 + ret i64 %r +} + +; @test8 +; CHECK: ret i64 undef +define i64 @test8() { + %r = sdiv i64 undef, 1 + ret i64 %r +} + +; @test9 +; CHECK: ret i64 0 +define i64 @test9() { + %r = urem i64 undef, 1 + ret i64 %r +} + +; @test10 +; CHECK: ret i64 0 +define i64 @test10() { + %r = srem i64 undef, 1 + ret i64 %r +} + +; @test11 +; CHECK: ret i64 undef +define i64 @test11() { + %r = shl i64 undef, undef + ret i64 %r +} + +; @test12 +; CHECK: ret i64 undef +define i64 @test12() { + %r = ashr i64 undef, undef + ret i64 %r +} + +; @test13 +; CHECK: ret i64 undef +define i64 @test13() { + %r = lshr i64 undef, undef + ret i64 %r +} + +; @test14 +; CHECK: ret i1 undef +define i1 @test14() { + %r = icmp slt i64 undef, undef + ret i1 %r +} + +; @test15 +; CHECK: ret i1 undef +define i1 @test15() { + %r = icmp ult i64 undef, undef + ret i1 %r +} + +; @test16 +; CHECK: ret i64 undef +define i64 @test16(i64 %a) { + %r = select i1 undef, i64 %a, i64 undef + ret i64 %r +} + +; @test17 +; CHECK: ret i64 undef +define i64 @test17(i64 %a) { + %r = select i1 undef, i64 undef, i64 %a + ret i64 %r +} -- cgit v1.1 From c4f24eb584f6b4dba3caba2ed766c7c4bf1bf8af Mon Sep 17 00:00:00 2001 From: Akira Hatanaka Date: Fri, 1 Jul 2011 01:04:43 +0000 Subject: Improve Mips back-end's handling of DBG_VALUE. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134224 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Mips/MipsAsmPrinter.cpp | 24 ++++++++++++++++ lib/Target/Mips/MipsInstrInfo.cpp | 9 ++++++ lib/Target/Mips/MipsInstrInfo.h | 5 ++++ lib/Target/Mips/MipsMCAsmInfo.cpp | 2 +- lib/Target/Mips/MipsRegisterInfo.cpp | 53 +++++++++++++++++++++--------------- 5 files changed, 70 insertions(+), 23 deletions(-) diff --git a/lib/Target/Mips/MipsAsmPrinter.cpp b/lib/Target/Mips/MipsAsmPrinter.cpp index 6f69ba3..78f69ea 100644 --- a/lib/Target/Mips/MipsAsmPrinter.cpp +++ b/lib/Target/Mips/MipsAsmPrinter.cpp @@ -38,6 +38,8 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Analysis/DebugInfo.h" + using namespace llvm; namespace { @@ -75,6 +77,10 @@ namespace { void EmitInstruction(const MachineInstr *MI) { SmallString<128> Str; raw_svector_ostream OS(Str); + + if (MI->isDebugValue()) + PrintDebugValueComment(MI, OS); + printInstruction(MI, OS); OutStreamer.EmitRawText(OS.str()); } @@ -86,6 +92,9 @@ namespace { virtual void EmitFunctionEntryLabel(); void EmitStartOfAsmFile(Module &M); + virtual MachineLocation getDebugValueLocation(const MachineInstr *MI) const; + + void PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS); }; } // end of anonymous namespace @@ -441,6 +450,21 @@ void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) { OutStreamer.EmitRawText(StringRef("\t.previous")); } +MachineLocation +MipsAsmPrinter::getDebugValueLocation(const MachineInstr *MI) const { + // Handles frame addresses emitted in MipsInstrInfo::emitFrameIndexDebugValue. + assert(MI->getNumOperands() == 4 && "Invalid no. of machine operands!"); + assert(MI->getOperand(0).isReg() && MI->getOperand(1).isImm() && + "Unexpected MachineOperand types"); + return MachineLocation(MI->getOperand(0).getReg(), + MI->getOperand(1).getImm()); +} + +void MipsAsmPrinter::PrintDebugValueComment(const MachineInstr *MI, + raw_ostream &OS) { + // TODO: implement +} + // Force static initialization. extern "C" void LLVMInitializeMipsAsmPrinter() { RegisterAsmPrinter X(TheMipsTarget); diff --git a/lib/Target/Mips/MipsInstrInfo.cpp b/lib/Target/Mips/MipsInstrInfo.cpp index 508d1c2..deab5e5 100644 --- a/lib/Target/Mips/MipsInstrInfo.cpp +++ b/lib/Target/Mips/MipsInstrInfo.cpp @@ -217,6 +217,15 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, llvm_unreachable("Register class not handled!"); } +MachineInstr* +MipsInstrInfo::emitFrameIndexDebugValue(MachineFunction &MF, int FrameIx, + uint64_t Offset, const MDNode *MDPtr, + DebugLoc DL) const { + MachineInstrBuilder MIB = BuildMI(MF, DL, get(Mips::DBG_VALUE)) + .addFrameIndex(FrameIx).addImm(0).addImm(Offset).addMetadata(MDPtr); + return &*MIB; +} + //===----------------------------------------------------------------------===// // Branch Analysis //===----------------------------------------------------------------------===// diff --git a/lib/Target/Mips/MipsInstrInfo.h b/lib/Target/Mips/MipsInstrInfo.h index abf6773..b7f8bec 100644 --- a/lib/Target/Mips/MipsInstrInfo.h +++ b/lib/Target/Mips/MipsInstrInfo.h @@ -224,6 +224,11 @@ public: const TargetRegisterClass *RC, const TargetRegisterInfo *TRI) const; + virtual MachineInstr* emitFrameIndexDebugValue(MachineFunction &MF, + int FrameIx, uint64_t Offset, + const MDNode *MDPtr, + DebugLoc DL) const; + virtual bool ReverseBranchCondition(SmallVectorImpl &Cond) const; diff --git a/lib/Target/Mips/MipsMCAsmInfo.cpp b/lib/Target/Mips/MipsMCAsmInfo.cpp index c86bf40..97ed878 100644 --- a/lib/Target/Mips/MipsMCAsmInfo.cpp +++ b/lib/Target/Mips/MipsMCAsmInfo.cpp @@ -16,7 +16,7 @@ using namespace llvm; MipsMCAsmInfo::MipsMCAsmInfo(const Target &T, StringRef TT) { AlignmentIsInBytes = false; - Data16bitsDirective = "\t.half\t"; + Data16bitsDirective = "\t.2byte\t"; Data32bitsDirective = "\t.4byte\t"; Data64bitsDirective = 0; PrivateGlobalPrefix = "$"; diff --git a/lib/Target/Mips/MipsRegisterInfo.cpp b/lib/Target/Mips/MipsRegisterInfo.cpp index 40774c9..202a1d4 100644 --- a/lib/Target/Mips/MipsRegisterInfo.cpp +++ b/lib/Target/Mips/MipsRegisterInfo.cpp @@ -35,6 +35,7 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/Analysis/DebugInfo.h" #define GET_REGINFO_MC_DESC #define GET_REGINFO_TARGET_DESC @@ -179,8 +180,29 @@ eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, << "spOffset : " << spOffset << "\n" << "stackSize : " << stackSize << "\n"); - int Offset; + const std::vector &CSI = MFI->getCalleeSavedInfo(); + int MinCSFI = 0; + int MaxCSFI = -1; + + if (CSI.size()) { + MinCSFI = CSI[0].getFrameIdx(); + MaxCSFI = CSI[CSI.size() - 1].getFrameIdx(); + } + + // The following stack frame objects are always referenced relative to $sp: + // 1. Outgoing arguments. + // 2. Pointer to dynamically allocated stack space. + // 3. Locations for callee-saved registers. + // Everything else is referenced relative to whatever register + // getFrameRegister() returns. + unsigned FrameReg; + if (MipsFI->isOutArgFI(FrameIndex) || MipsFI->isDynAllocFI(FrameIndex) || + (FrameIndex >= MinCSFI && FrameIndex <= MaxCSFI)) + FrameReg = Mips::SP; + else + FrameReg = getFrameRegister(MF); + // Calculate final offset. // - There is no need to change the offset if the frame object is one of the // following: an outgoing argument, pointer to a dynamically allocated @@ -188,12 +210,20 @@ eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, // - If the frame object is any of the following, its offset must be adjusted // by adding the size of the stack: // incoming argument, callee-saved register location or local variable. + int Offset; + if (MipsFI->isOutArgFI(FrameIndex) || MipsFI->isGPFI(FrameIndex) || MipsFI->isDynAllocFI(FrameIndex)) Offset = spOffset; else Offset = spOffset + stackSize; + if (MI.isDebugValue()) { + MI.getOperand(i).ChangeToRegister(FrameReg, false /*isDef*/); + MI.getOperand(i+1).ChangeToImmediate(Offset); + return; + } + Offset += MI.getOperand(i-1).getImm(); DEBUG(errs() << "Offset : " << Offset << "\n" << "<--------->\n"); @@ -202,28 +232,7 @@ eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, int NewImm = 0; MachineBasicBlock &MBB = *MI.getParent(); bool ATUsed; - unsigned FrameReg; - const std::vector &CSI = MFI->getCalleeSavedInfo(); - int MinCSFI = 0; - int MaxCSFI = -1; - - if (CSI.size()) { - MinCSFI = CSI[0].getFrameIdx(); - MaxCSFI = CSI[CSI.size() - 1].getFrameIdx(); - } - // The following stack frame objects are always referenced relative to $sp: - // 1. Outgoing arguments. - // 2. Pointer to dynamically allocated stack space. - // 3. Locations for callee-saved registers. - // Everything else is referenced relative to whatever register - // getFrameRegister() returns. - if (MipsFI->isOutArgFI(FrameIndex) || MipsFI->isDynAllocFI(FrameIndex) || - (FrameIndex >= MinCSFI && FrameIndex <= MaxCSFI)) - FrameReg = Mips::SP; - else - FrameReg = getFrameRegister(MF); - // Offset fits in the 16-bit field if (Offset < 0x8000 && Offset >= -0x8000) { NewReg = FrameReg; -- cgit v1.1 From 5e9ae090d8afd994c8c8e81779dd2c074ecf9369 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Fri, 1 Jul 2011 01:24:25 +0000 Subject: Don't inflate register classes used by inline asm. The constraints are represented by the register class of the original virtual register created for the inline asm. If the register class were included in the operand descriptor, we might be able to do this. For now, just give up on regclass inflation when inline asm is involved. No test case, this bug hasn't happened yet. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134226 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CalcSpillWeights.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/CodeGen/CalcSpillWeights.cpp b/lib/CodeGen/CalcSpillWeights.cpp index 74c43cc..e6b3bbc 100644 --- a/lib/CodeGen/CalcSpillWeights.cpp +++ b/lib/CodeGen/CalcSpillWeights.cpp @@ -203,6 +203,9 @@ void VirtRegAuxInfo::CalculateRegClass(unsigned reg) { // TRI doesn't have accurate enough information to model this yet. if (I.getOperand().getSubReg()) return; + // Inline asm instuctions don't remember their constraints. + if (I->isInlineAsm()) + return; const TargetRegisterClass *OpRC = TII->getRegClass(I->getDesc(), I.getOperandNo(), TRI); if (OpRC) -- cgit v1.1 From 1c8b97cbc03e0e1966d244a27b55e74bde35671e Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Fri, 1 Jul 2011 02:35:06 +0000 Subject: Check the liveinterval, not the kill flag. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134228 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/RegisterCoalescer.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/lib/CodeGen/RegisterCoalescer.cpp b/lib/CodeGen/RegisterCoalescer.cpp index 57156cb..76edc08 100644 --- a/lib/CodeGen/RegisterCoalescer.cpp +++ b/lib/CodeGen/RegisterCoalescer.cpp @@ -1197,7 +1197,8 @@ static unsigned ComputeUltimateVN(VNInfo *VNI, // which allows us to coalesce A and B. // MI is the definition of B. LR is the life range of A that includes // the slot just before B. If we return true, we add "B = X" to DupCopies. -static bool RegistersDefinedFromSameValue(const TargetRegisterInfo &tri, +static bool RegistersDefinedFromSameValue(LiveIntervals &li, + const TargetRegisterInfo &tri, CoalescerPair &CP, MachineInstr *MI, LiveRange *LR, SmallVector &DupCopies) { @@ -1207,14 +1208,16 @@ static bool RegistersDefinedFromSameValue(const TargetRegisterInfo &tri, if (!MI->isFullCopy() || CP.isPartial() || CP.isPhys()) return false; + unsigned Dst = MI->getOperand(0).getReg(); + unsigned Src = MI->getOperand(1).getReg(); + // FIXME: If "B = X" kills X, we have to move the kill back to its // previous use. For now we just avoid the optimization in that case. - if (MI->getOperand(1).isKill()) + SlotIndex CopyIdx = li.getInstructionIndex(MI).getNextIndex().getDefIndex(); + LiveInterval &SrcInt = li.getInterval(Src); + if (SrcInt.killedAt(CopyIdx)) return false; - unsigned Dst = MI->getOperand(0).getReg(); - unsigned Src = MI->getOperand(1).getReg(); - if (!TargetRegisterInfo::isVirtualRegister(Src) || !TargetRegisterInfo::isVirtualRegister(Dst)) return false; @@ -1332,7 +1335,7 @@ bool RegisterCoalescer::JoinIntervals(CoalescerPair &CP) { // from the RHS interval, we can use its value #. MachineInstr *MI = VNI->getCopy(); if (!CP.isCoalescable(MI) && - !RegistersDefinedFromSameValue(*tri_, CP, MI, lr, DupCopies)) + !RegistersDefinedFromSameValue(*li_, *tri_, CP, MI, lr, DupCopies)) continue; LHSValsDefinedFromRHS[VNI] = lr->valno; @@ -1359,7 +1362,7 @@ bool RegisterCoalescer::JoinIntervals(CoalescerPair &CP) { // from the LHS interval, we can use its value #. MachineInstr *MI = VNI->getCopy(); if (!CP.isCoalescable(MI) && - !RegistersDefinedFromSameValue(*tri_, CP, MI, lr, DupCopies)) + !RegistersDefinedFromSameValue(*li_, *tri_, CP, MI, lr, DupCopies)) continue; RHSValsDefinedFromLHS[VNI] = lr->valno; -- cgit v1.1 From fe11caaa73782e3182a4d4840ee00336dab9490a Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Fri, 1 Jul 2011 03:31:29 +0000 Subject: Fix off by one error. I misunderstood the comment about killedAt. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134229 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/RegisterCoalescer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/CodeGen/RegisterCoalescer.cpp b/lib/CodeGen/RegisterCoalescer.cpp index 76edc08..f525ccd 100644 --- a/lib/CodeGen/RegisterCoalescer.cpp +++ b/lib/CodeGen/RegisterCoalescer.cpp @@ -1213,7 +1213,7 @@ static bool RegistersDefinedFromSameValue(LiveIntervals &li, // FIXME: If "B = X" kills X, we have to move the kill back to its // previous use. For now we just avoid the optimization in that case. - SlotIndex CopyIdx = li.getInstructionIndex(MI).getNextIndex().getDefIndex(); + SlotIndex CopyIdx = li.getInstructionIndex(MI).getDefIndex(); LiveInterval &SrcInt = li.getInterval(Src); if (SrcInt.killedAt(CopyIdx)) return false; -- cgit v1.1 From 8f1bdac3eba0e065c8ebe2a9c671e299c1fc6797 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Fri, 1 Jul 2011 04:15:02 +0000 Subject: Avoid DenseMap lookup. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134231 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/RegisterCoalescer.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/CodeGen/RegisterCoalescer.cpp b/lib/CodeGen/RegisterCoalescer.cpp index f525ccd..3b982d6 100644 --- a/lib/CodeGen/RegisterCoalescer.cpp +++ b/lib/CodeGen/RegisterCoalescer.cpp @@ -1195,16 +1195,19 @@ static unsigned ComputeUltimateVN(VNInfo *VNI, // A = X // B = A // which allows us to coalesce A and B. -// MI is the definition of B. LR is the life range of A that includes +// VNI is the definition of B. LR is the life range of A that includes // the slot just before B. If we return true, we add "B = X" to DupCopies. static bool RegistersDefinedFromSameValue(LiveIntervals &li, const TargetRegisterInfo &tri, - CoalescerPair &CP, MachineInstr *MI, + CoalescerPair &CP, + VNInfo *VNI, LiveRange *LR, SmallVector &DupCopies) { // FIXME: This is very conservative. For example, we don't handle // physical registers. + MachineInstr *MI = VNI->getCopy(); + if (!MI->isFullCopy() || CP.isPartial() || CP.isPhys()) return false; @@ -1213,9 +1216,8 @@ static bool RegistersDefinedFromSameValue(LiveIntervals &li, // FIXME: If "B = X" kills X, we have to move the kill back to its // previous use. For now we just avoid the optimization in that case. - SlotIndex CopyIdx = li.getInstructionIndex(MI).getDefIndex(); LiveInterval &SrcInt = li.getInterval(Src); - if (SrcInt.killedAt(CopyIdx)) + if (SrcInt.killedAt(VNI->def)) return false; if (!TargetRegisterInfo::isVirtualRegister(Src) || @@ -1335,7 +1337,7 @@ bool RegisterCoalescer::JoinIntervals(CoalescerPair &CP) { // from the RHS interval, we can use its value #. MachineInstr *MI = VNI->getCopy(); if (!CP.isCoalescable(MI) && - !RegistersDefinedFromSameValue(*li_, *tri_, CP, MI, lr, DupCopies)) + !RegistersDefinedFromSameValue(*li_, *tri_, CP, VNI, lr, DupCopies)) continue; LHSValsDefinedFromRHS[VNI] = lr->valno; @@ -1362,7 +1364,7 @@ bool RegisterCoalescer::JoinIntervals(CoalescerPair &CP) { // from the LHS interval, we can use its value #. MachineInstr *MI = VNI->getCopy(); if (!CP.isCoalescable(MI) && - !RegistersDefinedFromSameValue(*li_, *tri_, CP, MI, lr, DupCopies)) + !RegistersDefinedFromSameValue(*li_, *tri_, CP, VNI, lr, DupCopies)) continue; RHSValsDefinedFromLHS[VNI] = lr->valno; -- cgit v1.1 From 3f9b9eb57dafc2a25a6e3d9ee570bd5a884b11e3 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Fri, 1 Jul 2011 04:40:50 +0000 Subject: Fix use after free. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134234 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/MC/SubtargetFeature.h | 2 +- lib/MC/SubtargetFeature.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/llvm/MC/SubtargetFeature.h b/include/llvm/MC/SubtargetFeature.h index ff726ec..fccff03 100644 --- a/include/llvm/MC/SubtargetFeature.h +++ b/include/llvm/MC/SubtargetFeature.h @@ -77,7 +77,7 @@ public: explicit SubtargetFeatures(const StringRef Initial = ""); /// Features string accessors. - StringRef getString() const; + std::string getString() const; /// Adding Features. void AddFeature(const StringRef String, bool IsEnabled = true); diff --git a/lib/MC/SubtargetFeature.cpp b/lib/MC/SubtargetFeature.cpp index 247f73a..c930baf 100644 --- a/lib/MC/SubtargetFeature.cpp +++ b/lib/MC/SubtargetFeature.cpp @@ -182,7 +182,7 @@ SubtargetFeatures::SubtargetFeatures(const StringRef Initial) { } -StringRef SubtargetFeatures::getString() const { +std::string SubtargetFeatures::getString() const { return Join(Features); } -- cgit v1.1 From 394d1f1948c1b5c9e902059104b08a4837dfbbee Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Fri, 1 Jul 2011 06:27:03 +0000 Subject: Fix likely typo, reduce number of instruction name collisions. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134235 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Scalar/ScalarReplAggregates.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Transforms/Scalar/ScalarReplAggregates.cpp b/lib/Transforms/Scalar/ScalarReplAggregates.cpp index 6fa3627..87e364d 100644 --- a/lib/Transforms/Scalar/ScalarReplAggregates.cpp +++ b/lib/Transforms/Scalar/ScalarReplAggregates.cpp @@ -1303,7 +1303,7 @@ static bool tryToMakeAllocaBePromotable(AllocaInst *AI, const TargetData *TD) { LoadInst *TrueLoad = Builder.CreateLoad(SI->getTrueValue(), LI->getName()+".t"); LoadInst *FalseLoad = - Builder.CreateLoad(SI->getFalseValue(), LI->getName()+".t"); + Builder.CreateLoad(SI->getFalseValue(), LI->getName()+".f"); // Transfer alignment and TBAA info if present. TrueLoad->setAlignment(LI->getAlignment()); -- cgit v1.1 From 24e11afad266498ca447649b8522e01ac2073798 Mon Sep 17 00:00:00 2001 From: Francois Pichet Date: Fri, 1 Jul 2011 09:23:41 +0000 Subject: Another misuse of StringRef. MSVC is very sensitive to that kind of error. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134236 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/MC/SubtargetFeature.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/MC/SubtargetFeature.cpp b/lib/MC/SubtargetFeature.cpp index c930baf..d72c346 100644 --- a/lib/MC/SubtargetFeature.cpp +++ b/lib/MC/SubtargetFeature.cpp @@ -53,14 +53,14 @@ static inline bool isEnabled(const StringRef Feature) { /// PrependFlag - Return a string with a prepended flag; '+' or '-'. /// -static inline StringRef PrependFlag(const StringRef Feature, +static inline std::string PrependFlag(const StringRef Feature, bool IsEnabled) { assert(!Feature.empty() && "Empty string"); if (hasFlag(Feature)) return Feature; std::string Prefix = IsEnabled ? "+" : "-"; Prefix += Feature; - return StringRef(Prefix); + return Prefix; } /// Split - Splits a string of comma separated items in to a vector of strings. -- cgit v1.1 From ed5bc470aab7097c30e5f881158112f7830472f3 Mon Sep 17 00:00:00 2001 From: Duncan Sands Date: Fri, 1 Jul 2011 12:01:00 +0000 Subject: Disable commit 134216 ("Add 134199 back, but disable the optimization when the second copy is a kill") to see if it fixes the i386 dragonegg buildbot, which is timing out because gcc built with dragonegg is going into an infinite loop. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134237 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/RegisterCoalescer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/CodeGen/RegisterCoalescer.cpp b/lib/CodeGen/RegisterCoalescer.cpp index 3b982d6..d5025b9 100644 --- a/lib/CodeGen/RegisterCoalescer.cpp +++ b/lib/CodeGen/RegisterCoalescer.cpp @@ -1203,6 +1203,7 @@ static bool RegistersDefinedFromSameValue(LiveIntervals &li, VNInfo *VNI, LiveRange *LR, SmallVector &DupCopies) { + return false; // To see if this fixes the i386 dragonegg buildbot miscompile. // FIXME: This is very conservative. For example, we don't handle // physical registers. -- cgit v1.1