diff options
author | Roman Divacky <rdivacky@FreeBSD.org> | 2010-01-01 10:31:22 +0000 |
---|---|---|
committer | Roman Divacky <rdivacky@FreeBSD.org> | 2010-01-01 10:31:22 +0000 |
commit | 1e7804dbd25b8dbf534c850355d70ad215206f4b (patch) | |
tree | dba00119388b84f9f44e6ec5e9129f807fd79ca3 /lib/Target/PIC16 | |
parent | 571945e6affd20b19264ec22495da418d0fbdbb4 (diff) |
Notes
Diffstat (limited to 'lib/Target/PIC16')
-rw-r--r-- | lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.cpp | 18 | ||||
-rw-r--r-- | lib/Target/PIC16/PIC16ISelDAGToDAG.h | 5 | ||||
-rw-r--r-- | lib/Target/PIC16/PIC16ISelLowering.cpp | 112 | ||||
-rw-r--r-- | lib/Target/PIC16/PIC16ISelLowering.h | 11 | ||||
-rw-r--r-- | lib/Target/PIC16/PIC16InstrInfo.td | 39 |
5 files changed, 132 insertions, 53 deletions
diff --git a/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.cpp b/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.cpp index e1f2587658ee2..87f5aad02a63c 100644 --- a/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.cpp +++ b/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.cpp @@ -170,7 +170,16 @@ void PIC16AsmPrinter::printOperand(const MachineInstr *MI, int opNum) { switch (MO.getType()) { case MachineOperand::MO_Register: - O << getRegisterName(MO.getReg()); + { + // For indirect load/store insns, the fsr name is printed as INDF. + std::string RegName = getRegisterName(MO.getReg()); + if ((MI->getOpcode() == PIC16::load_indirect) || + (MI->getOpcode() == PIC16::store_indirect)) + { + RegName.replace (0, 3, "INDF"); + } + O << RegName; + } return; case MachineOperand::MO_Immediate: @@ -263,10 +272,9 @@ void PIC16AsmPrinter::printLibcallDecls() { bool PIC16AsmPrinter::doInitialization(Module &M) { bool Result = AsmPrinter::doInitialization(M); - // FIXME:: This is temporary solution to generate the include file. - // The processor should be passed to llc as in input and the header file - // should be generated accordingly. - O << "\n\t#include P16F1937.INC\n"; + // Every asmbly contains these std headers. + O << "\n#include p16f1xxx.inc"; + O << "\n#include stdmacros.inc"; // Set the section names for all globals. for (Module::global_iterator I = M.global_begin(), E = M.global_end(); diff --git a/lib/Target/PIC16/PIC16ISelDAGToDAG.h b/lib/Target/PIC16/PIC16ISelDAGToDAG.h index 3a2f6b47b37e1..d9172f2b3622b 100644 --- a/lib/Target/PIC16/PIC16ISelDAGToDAG.h +++ b/lib/Target/PIC16/PIC16ISelDAGToDAG.h @@ -36,7 +36,10 @@ class VISIBILITY_HIDDEN PIC16DAGToDAGISel : public SelectionDAGISel { public: explicit PIC16DAGToDAGISel(PIC16TargetMachine &tm) : SelectionDAGISel(tm), - TM(tm), PIC16Lowering(*TM.getTargetLowering()) {} + TM(tm), PIC16Lowering(*TM.getTargetLowering()) { + // Keep PIC16 specific DAGISel to use during the lowering + PIC16Lowering.ISel = this; + } // Pass Name virtual const char *getPassName() const { diff --git a/lib/Target/PIC16/PIC16ISelLowering.cpp b/lib/Target/PIC16/PIC16ISelLowering.cpp index 71c3d37341096..9f093e817df64 100644 --- a/lib/Target/PIC16/PIC16ISelLowering.cpp +++ b/lib/Target/PIC16/PIC16ISelLowering.cpp @@ -226,6 +226,7 @@ PIC16TargetLowering::PIC16TargetLowering(PIC16TargetMachine &TM) setLibcallName(RTLIB::DIV_F32, getIntrinsicName(RTLIB::DIV_F32)); // Floationg point comparison + setLibcallName(RTLIB::O_F32, getIntrinsicName(RTLIB::O_F32)); setLibcallName(RTLIB::UO_F32, getIntrinsicName(RTLIB::UO_F32)); setLibcallName(RTLIB::OLE_F32, getIntrinsicName(RTLIB::OLE_F32)); setLibcallName(RTLIB::OGE_F32, getIntrinsicName(RTLIB::OGE_F32)); @@ -371,6 +372,11 @@ PIC16TargetLowering::getSetCCResultType(EVT ValType) const { return MVT::i8; } +MVT::SimpleValueType +PIC16TargetLowering::getCmpLibcallReturnType() const { + return MVT::i8; +} + /// The type legalizer framework of generating legalizer can generate libcalls /// only when the operand/result types are illegal. /// PIC16 needs to generate libcalls even for the legal types (i8) for some ops. @@ -413,7 +419,8 @@ PIC16TargetLowering::MakePIC16Libcall(PIC16ISD::PIC16Libcall Call, LowerCallTo(DAG.getEntryNode(), RetTy, isSigned, !isSigned, false, false, 0, CallingConv::C, false, /*isReturnValueUsed=*/true, - Callee, Args, DAG, dl); + Callee, Args, DAG, dl, + DAG.GetOrdering(DAG.getEntryNode().getNode())); return CallInfo.first; } @@ -924,7 +931,7 @@ SDValue PIC16TargetLowering::ExpandLoad(SDNode *N, SelectionDAG &DAG) { } else if (VT == MVT::i16) { BP = DAG.getNode(ISD::BUILD_PAIR, dl, VT, PICLoads[0], PICLoads[1]); - if (MemVT == MVT::i8) + if ((MemVT == MVT::i8) || (MemVT == MVT::i1)) Chain = getChain(PICLoads[0]); else Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, @@ -936,7 +943,7 @@ SDValue PIC16TargetLowering::ExpandLoad(SDNode *N, SelectionDAG &DAG) { BPs[1] = DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i16, PICLoads[2], PICLoads[3]); BP = DAG.getNode(ISD::BUILD_PAIR, dl, VT, BPs[0], BPs[1]); - if (MemVT == MVT::i8) + if ((MemVT == MVT::i8) || (MemVT == MVT::i1)) Chain = getChain(PICLoads[0]); else if (MemVT == MVT::i16) Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, @@ -1270,7 +1277,6 @@ PIC16TargetLowering::LowerReturn(SDValue Chain, std::string FuncName = F->getName(); const char *tmpName = createESName(PAN::getFrameLabel(FuncName)); - SDVTList VTs = DAG.getVTList (MVT::i8, MVT::Other); SDValue ES = DAG.getTargetExternalSymbol(tmpName, MVT::i8); SDValue BS = DAG.getConstant(1, MVT::i8); SDValue RetVal; @@ -1482,7 +1488,8 @@ bool PIC16TargetLowering::isDirectLoad(const SDValue Op) { // operand no. of the operand to be converted in 'MemOp'. Remember, PIC16 has // no instruction that can operation on two registers. Most insns take // one register and one memory operand (addwf) / Constant (addlw). -bool PIC16TargetLowering::NeedToConvertToMemOp(SDValue Op, unsigned &MemOp) { +bool PIC16TargetLowering::NeedToConvertToMemOp(SDValue Op, unsigned &MemOp, + SelectionDAG &DAG) { // If one of the operand is a constant, return false. if (Op.getOperand(0).getOpcode() == ISD::Constant || Op.getOperand(1).getOpcode() == ISD::Constant) @@ -1491,11 +1498,33 @@ bool PIC16TargetLowering::NeedToConvertToMemOp(SDValue Op, unsigned &MemOp) { // Return false if one of the operands is already a direct // load and that operand has only one use. if (isDirectLoad(Op.getOperand(0))) { - if (Op.getOperand(0).hasOneUse()) - return false; - else - MemOp = 0; + if (Op.getOperand(0).hasOneUse()) { + // Legal and profitable folding check uses the NodeId of DAG nodes. + // This NodeId is assigned by topological order. Therefore first + // assign topological order then perform legal and profitable check. + // Note:- Though this ordering is done before begining with legalization, + // newly added node during legalization process have NodeId=-1 (NewNode) + // therefore before performing any check proper ordering of the node is + // required. + DAG.AssignTopologicalOrder(); + + // Direct load operands are folded in binary operations. But before folding + // verify if this folding is legal. Fold only if it is legal otherwise + // convert this direct load to a separate memory operation. + if(ISel->IsLegalAndProfitableToFold(Op.getOperand(0).getNode(), + Op.getNode(), Op.getNode())) + return false; + else + MemOp = 0; + } } + + // For operations that are non-cummutative there is no need to check + // for right operand because folding right operand may result in + // incorrect operation. + if (! SelectionDAG::isCommutativeBinOp(Op.getOpcode())) + return true; + if (isDirectLoad(Op.getOperand(1))) { if (Op.getOperand(1).hasOneUse()) return false; @@ -1514,7 +1543,7 @@ SDValue PIC16TargetLowering::LowerBinOp(SDValue Op, SelectionDAG &DAG) { assert (Op.getValueType() == MVT::i8 && "illegal Op to lower"); unsigned MemOp = 1; - if (NeedToConvertToMemOp(Op, MemOp)) { + if (NeedToConvertToMemOp(Op, MemOp, DAG)) { // Put one value on stack. SDValue NewVal = ConvertToMemOperand (Op.getOperand(MemOp), DAG, dl); @@ -1533,7 +1562,7 @@ SDValue PIC16TargetLowering::LowerADD(SDValue Op, SelectionDAG &DAG) { assert (Op.getValueType() == MVT::i8 && "illegal add to lower"); DebugLoc dl = Op.getDebugLoc(); unsigned MemOp = 1; - if (NeedToConvertToMemOp(Op, MemOp)) { + if (NeedToConvertToMemOp(Op, MemOp, DAG)) { // Put one value on stack. SDValue NewVal = ConvertToMemOperand (Op.getOperand(MemOp), DAG, dl); @@ -1561,30 +1590,47 @@ SDValue PIC16TargetLowering::LowerSUB(SDValue Op, SelectionDAG &DAG) { DebugLoc dl = Op.getDebugLoc(); // We should have handled larger operands in type legalizer itself. assert (Op.getValueType() == MVT::i8 && "illegal sub to lower"); + unsigned MemOp = 1; + SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Flag); - // Nothing to do if the first operand is already a direct load and it has - // only one use. - if (isDirectLoad(Op.getOperand(0)) && Op.getOperand(0).hasOneUse()) - return Op; - - // Put first operand on stack. - SDValue NewVal = ConvertToMemOperand (Op.getOperand(0), DAG, dl); + // Since we don't have an instruction for X - c , + // we can change it to X + (-c) + ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1)); + if (C && (Op.getOpcode() == ISD::SUB)) + { + return DAG.getNode(ISD::ADD, + dl, MVT::i8, Op.getOperand(0), + DAG.getConstant(0-(C->getZExtValue()), MVT::i8)); + } - SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Flag); - switch (Op.getOpcode()) { - default: - assert (0 && "Opcode unknown."); - case ISD::SUBE: - return DAG.getNode(Op.getOpcode(), dl, Tys, NewVal, Op.getOperand(1), - Op.getOperand(2)); - break; - case ISD::SUBC: - return DAG.getNode(Op.getOpcode(), dl, Tys, NewVal, Op.getOperand(1)); - break; - case ISD::SUB: - return DAG.getNode(Op.getOpcode(), dl, MVT::i8, NewVal, Op.getOperand(1)); - break; - } + if (NeedToConvertToMemOp(Op, MemOp, DAG) || + (isDirectLoad(Op.getOperand(1)) && + (!isDirectLoad(Op.getOperand(0))) && + (Op.getOperand(0).getOpcode() != ISD::Constant))) + { + // Put first operand on stack. + SDValue NewVal = ConvertToMemOperand (Op.getOperand(0), DAG, dl); + + switch (Op.getOpcode()) { + default: + assert (0 && "Opcode unknown."); + case ISD::SUBE: + return DAG.getNode(Op.getOpcode(), + dl, Tys, NewVal, Op.getOperand(1), + Op.getOperand(2)); + break; + case ISD::SUBC: + return DAG.getNode(Op.getOpcode(), + dl, Tys, NewVal, Op.getOperand(1)); + break; + case ISD::SUB: + return DAG.getNode(Op.getOpcode(), + dl, MVT::i8, NewVal, Op.getOperand(1)); + break; + } + } + else + return Op; } void PIC16TargetLowering::InitReservedFrameCount(const Function *F) { diff --git a/lib/Target/PIC16/PIC16ISelLowering.h b/lib/Target/PIC16/PIC16ISelLowering.h index 286ed2411ef89..afdd4b4364170 100644 --- a/lib/Target/PIC16/PIC16ISelLowering.h +++ b/lib/Target/PIC16/PIC16ISelLowering.h @@ -18,6 +18,7 @@ #include "PIC16.h" #include "PIC16Subtarget.h" #include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/CodeGen/SelectionDAGISel.h" #include "llvm/Target/TargetLowering.h" #include <map> @@ -83,6 +84,7 @@ namespace llvm { virtual const char *getTargetNodeName(unsigned Opcode) const; /// getSetCCResultType - Return the ISD::SETCC ValueType virtual MVT::SimpleValueType getSetCCResultType(EVT ValType) const; + virtual MVT::SimpleValueType getCmpLibcallReturnType() const; SDValue LowerShift(SDValue Op, SelectionDAG &DAG); SDValue LowerMUL(SDValue Op, SelectionDAG &DAG); SDValue LowerADD(SDValue Op, SelectionDAG &DAG); @@ -216,7 +218,9 @@ namespace llvm { // This function checks if we need to put an operand of an operation on // stack and generate a load or not. - bool NeedToConvertToMemOp(SDValue Op, unsigned &MemOp); + // DAG parameter is required to access DAG information during + // analysis. + bool NeedToConvertToMemOp(SDValue Op, unsigned &MemOp, SelectionDAG &DAG); /// Subtarget - Keep a pointer to the PIC16Subtarget around so that we can /// make the right decision when generating code for different targets. @@ -239,6 +243,11 @@ namespace llvm { // Check if operation has a direct load operand. inline bool isDirectLoad(const SDValue Op); + public: + // Keep a pointer to SelectionDAGISel to access its public + // interface (It is required during legalization) + SelectionDAGISel *ISel; + private: // The frameindexes generated for spill/reload are stack based. // This maps maintain zero based indexes for these FIs. diff --git a/lib/Target/PIC16/PIC16InstrInfo.td b/lib/Target/PIC16/PIC16InstrInfo.td index 5eec6c4e66b5c..24df251b50887 100644 --- a/lib/Target/PIC16/PIC16InstrInfo.td +++ b/lib/Target/PIC16/PIC16InstrInfo.td @@ -151,7 +151,7 @@ let mayStore = 1 in class BinOpWF<bits<6> OpCode, string OpcStr, SDNode OpNode>: ByteFormat<OpCode, (outs), (ins GPR:$src, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi), - !strconcat(OpcStr, " $ptrlo + $offset"), + !strconcat(OpcStr, " $ptrlo + $offset, F"), [(PIC16Store (OpNode GPR:$src, (PIC16Load diraddr:$ptrlo, (i8 imm:$ptrhi), (i8 imm:$offset))), @@ -161,7 +161,7 @@ class BinOpWF<bits<6> OpCode, string OpcStr, SDNode OpNode>: // W = W Op L : Do Op of L with W and place result in W. let isTwoAddress = 1 in -class BinOpLW<bits<6> opcode, string OpcStr, SDNode OpNode> : +class BinOpWL<bits<6> opcode, string OpcStr, SDNode OpNode> : LiteralFormat<opcode, (outs GPR:$dst), (ins GPR:$src, i8imm:$literal), !strconcat(OpcStr, " $literal"), @@ -404,33 +404,46 @@ def subwf_cc: SUBWF<0, "subwf", PIC16Subcc>; // addlw let Defs = [STATUS] in { -def addlw_1 : BinOpLW<0, "addlw", add>; -def addlw_2 : BinOpLW<0, "addlw", addc>; +def addlw_1 : BinOpWL<0, "addlw", add>; +def addlw_2 : BinOpWL<0, "addlw", addc>; let Uses = [STATUS] in -def addlwc : BinOpLW<0, "addlwc", adde>; // With Carry. (Assembler macro). +def addlwc : BinOpWL<0, "addlwc", adde>; // With Carry. (Assembler macro). // bitwise operations involving a literal and w. -def andlw : BinOpLW<0, "andlw", and>; -def xorlw : BinOpLW<0, "xorlw", xor>; -def orlw : BinOpLW<0, "iorlw", or>; +def andlw : BinOpWL<0, "andlw", and>; +def xorlw : BinOpWL<0, "xorlw", xor>; +def orlw : BinOpWL<0, "iorlw", or>; } // sublw // W = C - W ; sub W from literal. (Without borrow). let isTwoAddress = 1 in -class SUBLW<bits<6> opcode, SDNode OpNode> : +class SUBLW<bits<6> opcode, string OpcStr, SDNode OpNode> : LiteralFormat<opcode, (outs GPR:$dst), (ins GPR:$src, i8imm:$literal), - "sublw $literal", + !strconcat(OpcStr, " $literal"), [(set GPR:$dst, (OpNode (i8 imm:$literal), GPR:$src))]>; +// subwl +// W = W - C ; sub literal from W (Without borrow). +let isTwoAddress = 1 in +class SUBWL<bits<6> opcode, string OpcStr, SDNode OpNode> : + LiteralFormat<opcode, (outs GPR:$dst), + (ins GPR:$src, i8imm:$literal), + !strconcat(OpcStr, " $literal"), + [(set GPR:$dst, (OpNode GPR:$src, (i8 imm:$literal)))]>; let Defs = [STATUS] in { -def sublw_1 : SUBLW<0, sub>; -def sublw_2 : SUBLW<0, subc>; +def sublw_1 : SUBLW<0, "sublw", sub>; +def sublw_2 : SUBLW<0, "sublw", subc>; +def sublw_3 : SUBLW<0, "sublwb", sube>; // With borrow (Assembler macro). + +def sublw_4 : SUBWL<0, "subwl", sub>; // Assembler macro replace with addlw +def sublw_5 : SUBWL<0, "subwl", subc>; // Assembler macro replace with addlw +def sublw_6 : SUBWL<0, "subwlb", sube>; // With borrow (Assembler macro). } let Defs = [STATUS], isTerminator = 1 in -def sublw_cc : SUBLW<0, PIC16Subcc>; +def sublw_cc : SUBLW<0, "sublw", PIC16Subcc>; // Call instruction. let isCall = 1, |