//===-- PIC16ISelLowering.cpp - PIC16 DAG Lowering Implementation ---------===// // // 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 interfaces that PIC16 uses to lower LLVM code into a // selection DAG. // //===----------------------------------------------------------------------===// #define DEBUG_TYPE "pic16-lower" #include "PIC16ISelLowering.h" #include "PIC16TargetMachine.h" #include "llvm/DerivedTypes.h" #include "llvm/Function.h" #include "llvm/Intrinsics.h" #include "llvm/CallingConv.h" #include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/SelectionDAGISel.h" #include "llvm/CodeGen/ValueTypes.h" #include "llvm/Support/Debug.h" #include #include using namespace llvm; const char *PIC16TargetLowering:: getTargetNodeName(unsigned Opcode) const { switch (Opcode) { case PIC16ISD::Hi : return "PIC16ISD::Hi"; case PIC16ISD::Lo : return "PIC16ISD::Lo"; case PIC16ISD::Package : return "PIC16ISD::Package"; case PIC16ISD::Wrapper : return "PIC16ISD::Wrapper"; case PIC16ISD::SetBank : return "PIC16ISD::SetBank"; case PIC16ISD::SetPage : return "PIC16ISD::SetPage"; case PIC16ISD::Branch : return "PIC16ISD::Branch"; case PIC16ISD::Cmp : return "PIC16ISD::Cmp"; case PIC16ISD::BTFSS : return "PIC16ISD::BTFSS"; case PIC16ISD::BTFSC : return "PIC16ISD::BTFSC"; case PIC16ISD::XORCC : return "PIC16ISD::XORCC"; case PIC16ISD::SUBCC : return "PIC16ISD::SUBCC"; default : return NULL; } } PIC16TargetLowering:: PIC16TargetLowering(PIC16TargetMachine &TM): TargetLowering(TM) { // Set up the register classes. addRegisterClass(MVT::i8, PIC16::CPURegsRegisterClass); addRegisterClass(MVT::i16, PIC16::PTRRegsRegisterClass); // Load extented operations for i1 types must be promoted . setLoadXAction(ISD::EXTLOAD, MVT::i1, Promote); setLoadXAction(ISD::ZEXTLOAD, MVT::i1, Promote); setLoadXAction(ISD::SEXTLOAD, MVT::i1, Promote); setOperationAction(ISD::ADD, MVT::i1, Promote); setOperationAction(ISD::ADD, MVT::i8, Legal); setOperationAction(ISD::ADD, MVT::i16, Custom); setOperationAction(ISD::ADD, MVT::i32, Expand); setOperationAction(ISD::ADD, MVT::i64, Expand); setOperationAction(ISD::SUB, MVT::i1, Promote); setOperationAction(ISD::SUB, MVT::i8, Legal); setOperationAction(ISD::SUB, MVT::i16, Custom); setOperationAction(ISD::SUB, MVT::i32, Expand); setOperationAction(ISD::SUB, MVT::i64, Expand); setOperationAction(ISD::ADDC, MVT::i1, Promote); setOperationAction(ISD::ADDC, MVT::i8, Legal); setOperationAction(ISD::ADDC, MVT::i16, Custom); setOperationAction(ISD::ADDC, MVT::i32, Expand); setOperationAction(ISD::ADDC, MVT::i64, Expand); setOperationAction(ISD::ADDE, MVT::i1, Promote); setOperationAction(ISD::ADDE, MVT::i8, Legal); setOperationAction(ISD::ADDE, MVT::i16, Custom); setOperationAction(ISD::ADDE, MVT::i32, Expand); setOperationAction(ISD::ADDE, MVT::i64, Expand); setOperationAction(ISD::SUBC, MVT::i1, Promote); setOperationAction(ISD::SUBC, MVT::i8, Legal); setOperationAction(ISD::SUBC, MVT::i16, Custom); setOperationAction(ISD::SUBC, MVT::i32, Expand); setOperationAction(ISD::SUBC, MVT::i64, Expand); setOperationAction(ISD::SUBE, MVT::i1, Promote); setOperationAction(ISD::SUBE, MVT::i8, Legal); setOperationAction(ISD::SUBE, MVT::i16, Custom); setOperationAction(ISD::SUBE, MVT::i32, Expand); setOperationAction(ISD::SUBE, MVT::i64, Expand); // PIC16 does not have these NodeTypes below. setOperationAction(ISD::SETCC, MVT::i1, Expand); setOperationAction(ISD::SETCC, MVT::i8, Expand); setOperationAction(ISD::SETCC, MVT::Other, Expand); setOperationAction(ISD::SELECT_CC, MVT::i1, Custom); setOperationAction(ISD::SELECT_CC, MVT::i8, Custom); setOperationAction(ISD::BRCOND, MVT::i1, Expand); setOperationAction(ISD::BRCOND, MVT::i8, Expand); setOperationAction(ISD::BRCOND, MVT::Other, Expand); setOperationAction(ISD::BR_CC, MVT::i1, Custom); setOperationAction(ISD::BR_CC, MVT::i8, Custom); setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); // FIXME: Do we really need to Custom lower the GA ?? setOperationAction(ISD::GlobalAddress, MVT::i8, Custom); setOperationAction(ISD::RET, MVT::Other, Custom); setOperationAction(ISD::CTPOP, MVT::i32, Expand); setOperationAction(ISD::CTTZ, MVT::i32, Expand); setOperationAction(ISD::CTLZ, MVT::i32, Expand); setOperationAction(ISD::ROTL, MVT::i32, Expand); setOperationAction(ISD::ROTR, MVT::i32, Expand); setOperationAction(ISD::BSWAP, MVT::i32, Expand); setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand); setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand); setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand); // We don't have line number support yet. setOperationAction(ISD::DBG_STOPPOINT, MVT::Other, Expand); setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand); setOperationAction(ISD::DBG_LABEL, MVT::Other, Expand); setOperationAction(ISD::EH_LABEL, MVT::Other, Expand); // Use the default for now. setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand); setOperationAction(ISD::LOAD, MVT::i1, Promote); setOperationAction(ISD::LOAD, MVT::i8, Legal); setTargetDAGCombine(ISD::LOAD); setTargetDAGCombine(ISD::STORE); setTargetDAGCombine(ISD::ADDE); setTargetDAGCombine(ISD::ADDC); setTargetDAGCombine(ISD::ADD); setTargetDAGCombine(ISD::SUBE); setTargetDAGCombine(ISD::SUBC); setTargetDAGCombine(ISD::SUB); setStackPointerRegisterToSaveRestore(PIC16::STKPTR); computeRegisterProperties(); } SDOperand PIC16TargetLowering:: LowerOperation(SDOperand Op, SelectionDAG &DAG) { SDVTList VTList16 = DAG.getVTList(MVT::i16, MVT::i16, MVT::Other); switch (Op.getOpcode()) { case ISD::STORE: DOUT << "reduce store\n"; break; case ISD::FORMAL_ARGUMENTS: DOUT << "==== lowering formal args\n"; return LowerFORMAL_ARGUMENTS(Op, DAG); case ISD::GlobalAddress: DOUT << "==== lowering GA\n"; return LowerGlobalAddress(Op, DAG); case ISD::RET: DOUT << "==== lowering ret\n"; return LowerRET(Op, DAG); case ISD::FrameIndex: DOUT << "==== lowering frame index\n"; return LowerFrameIndex(Op, DAG); case ISD::ADDE: DOUT << "==== lowering adde\n"; break; case ISD::LOAD: case ISD::ADD: break; case ISD::BR_CC: DOUT << "==== lowering BR_CC\n"; return LowerBR_CC(Op, DAG); } // end switch. return SDOperand(); } //===----------------------------------------------------------------------===// // Lower helper functions //===----------------------------------------------------------------------===// SDOperand PIC16TargetLowering::LowerBR_CC(SDOperand Op, SelectionDAG &DAG) { MVT VT = Op.getValueType(); SDOperand Chain = Op.getOperand(0); ISD::CondCode CC = cast(Op.getOperand(1))->get(); SDOperand LHS = Op.getOperand(2); SDOperand RHS = Op.getOperand(3); SDOperand JumpVal = Op.getOperand(4); SDOperand Result; unsigned cmpOpcode; unsigned branchOpcode; SDOperand branchOperand; SDOperand StatusReg = DAG.getRegister(PIC16::STATUSREG, MVT::i8); SDOperand CPUReg = DAG.getRegister(PIC16::WREG, MVT::i8); switch(CC) { default: assert(0 && "This condition code is not handled yet!!"); abort(); case ISD::SETNE: DOUT << "setne\n"; cmpOpcode = PIC16ISD::XORCC; branchOpcode = PIC16ISD::BTFSS; branchOperand = DAG.getConstant(2, MVT::i8); break; case ISD::SETEQ: DOUT << "seteq\n"; cmpOpcode = PIC16ISD::XORCC; branchOpcode = PIC16ISD::BTFSC; branchOperand = DAG.getConstant(2, MVT::i8); break; case ISD::SETGT: assert(0 && "Greater Than condition code is not handled yet!!"); abort(); break; case ISD::SETGE: DOUT << "setge\n"; cmpOpcode = PIC16ISD::SUBCC; branchOpcode = PIC16ISD::BTFSS; branchOperand = DAG.getConstant(1, MVT::i8); break; case ISD::SETLT: DOUT << "setlt\n"; cmpOpcode = PIC16ISD::SUBCC; branchOpcode = PIC16ISD::BTFSC; branchOperand = DAG.getConstant(1,MVT::i8); break; case ISD::SETLE: assert(0 && "Less Than Equal condition code is not handled yet!!"); abort(); break; } // End of Switch SDVTList VTList = DAG.getVTList(MVT::i8, MVT::Flag); SDOperand CmpValue = DAG.getNode(cmpOpcode, VTList, LHS, RHS).getValue(1); Result = DAG.getNode(branchOpcode, VT, Chain, JumpVal, branchOperand, StatusReg, CmpValue); return Result; } //===----------------------------------------------------------------------===// // Misc Lower Operation implementation //===----------------------------------------------------------------------===// // LowerGlobalAddress - Create a constant pool entry for global value // and wrap it in a wrapper node. SDOperand PIC16TargetLowering::LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG) { MVT PtrVT = getPointerTy(); GlobalAddressSDNode *GSDN = cast(Op); GlobalValue *GV = GSDN->getGlobal(); // FIXME: for now only do the ram. SDOperand CPAddr = DAG.getTargetConstantPool(GV, PtrVT, 2); SDOperand CPBank = DAG.getNode(PIC16ISD::SetBank, MVT::i8, CPAddr); CPAddr = DAG.getNode(PIC16ISD::Wrapper, MVT::i8, CPAddr,CPBank); return CPAddr; } SDOperand PIC16TargetLowering::LowerRET(SDOperand Op, SelectionDAG &DAG) { switch(Op.getNumOperands()) { default: assert(0 && "Do not know how to return this many arguments!"); abort(); case 1: return SDOperand(); // ret void is legal } } SDOperand PIC16TargetLowering::LowerFrameIndex(SDOperand N, SelectionDAG &DAG) { if (FrameIndexSDNode *FIN = dyn_cast(N)) { return DAG.getTargetFrameIndex(FIN->getIndex(), MVT::i32); } return N; } SDOperand PIC16TargetLowering::LowerLOAD(SDNode *N, SelectionDAG &DAG, DAGCombinerInfo &DCI) const { SDOperand Outs[2]; SDOperand TF; //TokenFactor SDOperand OutChains[2]; SDOperand Chain = N->getOperand(0); SDOperand Src = N->getOperand(1); SDOperand retVal; SDVTList VTList; // If this load is directly stored, replace the load value with the stored // value. // FIXME: Handle store large -> read small portion. // FIXME: Handle TRUNCSTORE/LOADEXT LoadSDNode *LD = cast(N); SDOperand Ptr = LD->getBasePtr(); if (LD->getExtensionType() == ISD::NON_EXTLOAD) { if (ISD::isNON_TRUNCStore(Chain.Val)) { StoreSDNode *PrevST = cast(Chain); if (PrevST->getBasePtr() == Ptr && PrevST->getValue().getValueType() == N->getValueType(0)) return DCI.CombineTo(N, Chain.getOperand(1), Chain); } } if (N->getValueType(0) != MVT::i16) return SDOperand(); SDOperand toWorklist; Outs[0] = DAG.getLoad(MVT::i8, Chain, Src, NULL, 0); toWorklist = DAG.getNode(ISD::ADD, MVT::i16, Src, DAG.getConstant(1, MVT::i16)); Outs[1] = DAG.getLoad(MVT::i8, Chain, toWorklist, NULL, 0); // FIXME: Add to worklist may not be needed. // It is meant to merge sequences of add with constant into one. DCI.AddToWorklist(toWorklist.Val); // Create the tokenfactors and carry it on to the build_pair node OutChains[0] = Outs[0].getValue(1); OutChains[1] = Outs[1].getValue(1); TF = DAG.getNode(ISD::TokenFactor, MVT::Other, &OutChains[0], 2); VTList = DAG.getVTList(MVT::i16, MVT::Flag); retVal = DAG.getNode (PIC16ISD::Package, VTList, &Outs[0], 2); DCI.CombineTo (N, retVal, TF); return retVal; } SDOperand PIC16TargetLowering::LowerADDSUB(SDNode *N, SelectionDAG &DAG, DAGCombinerInfo &DCI) const { bool changed = false; int i; SDOperand LoOps[3], HiOps[3]; SDOperand OutOps[3]; // [0]:left, [1]:right, [2]:carry SDOperand InOp[2]; SDOperand retVal; SDOperand as1,as2; SDVTList VTList; unsigned AS = 0, ASE = 0, ASC=0; InOp[0] = N->getOperand(0); InOp[1] = N->getOperand(1); switch (N->getOpcode()) { case ISD::ADD: if (InOp[0].getOpcode() == ISD::Constant && InOp[1].getOpcode() == ISD::Constant) { ConstantSDNode *CST0 = dyn_cast(InOp[0]); ConstantSDNode *CST1 = dyn_cast(InOp[1]); return DAG.getConstant(CST0->getValue() + CST1->getValue(), MVT::i16); } break; case ISD::ADDE: case ISD::ADDC: AS = ISD::ADD; ASE = ISD::ADDE; ASC = ISD::ADDC; break; case ISD::SUB: if (InOp[0].getOpcode() == ISD::Constant && InOp[1].getOpcode() == ISD::Constant) { ConstantSDNode *CST0 = dyn_cast(InOp[0]); ConstantSDNode *CST1 = dyn_cast(InOp[1]); return DAG.getConstant(CST0->getValue() - CST1->getValue(), MVT::i16); } break; case ISD::SUBE: case ISD::SUBC: AS = ISD::SUB; ASE = ISD::SUBE; ASC = ISD::SUBC; break; } // end switch. assert ((N->getValueType(0) == MVT::i16) && "expecting an MVT::i16 node for lowering"); assert ((N->getOperand(0).getValueType() == MVT::i16) && (N->getOperand(1).getValueType() == MVT::i16) && "both inputs to addx/subx:i16 must be i16"); for (i = 0; i < 2; i++) { if (InOp[i].getOpcode() == ISD::GlobalAddress) { // We don't want to lower subs/adds with global address yet. return SDOperand(); } else if (InOp[i].getOpcode() == ISD::Constant) { changed = true; ConstantSDNode *CST = dyn_cast(InOp[i]); LoOps[i] = DAG.getConstant(CST->getValue() & 0xFF, MVT::i8); HiOps[i] = DAG.getConstant(CST->getValue() >> 8, MVT::i8); } else if (InOp[i].getOpcode() == PIC16ISD::Package) { LoOps[i] = InOp[i].getOperand(0); HiOps[i] = InOp[i].getOperand(1); } else if (InOp[i].getOpcode() == ISD::LOAD) { changed = true; // LowerLOAD returns a Package node or it may combine and return // anything else. SDOperand lowered = LowerLOAD(InOp[i].Val, DAG, DCI); // So If LowerLOAD returns something other than Package, // then just call ADD again. if (lowered.getOpcode() != PIC16ISD::Package) return LowerADDSUB(N, DAG, DCI); LoOps[i] = lowered.getOperand(0); HiOps[i] = lowered.getOperand(1); } else if ((InOp[i].getOpcode() == ISD::ADD) || (InOp[i].getOpcode() == ISD::ADDE) || (InOp[i].getOpcode() == ISD::ADDC) || (InOp[i].getOpcode() == ISD::SUB) || (InOp[i].getOpcode() == ISD::SUBE) || (InOp[i].getOpcode() == ISD::SUBC)) { changed = true; // Must call LowerADDSUB recursively here, // LowerADDSUB returns a Package node. SDOperand lowered = LowerADDSUB(InOp[i].Val, DAG, DCI); LoOps[i] = lowered.getOperand(0); HiOps[i] = lowered.getOperand(1); } else if (InOp[i].getOpcode() == ISD::SIGN_EXTEND) { // FIXME: I am just zero extending. for now. changed = true; LoOps[i] = InOp[i].getOperand(0); HiOps[i] = DAG.getConstant(0, MVT::i8); } else { DAG.setGraphColor(N, "blue"); DAG.viewGraph(); assert (0 && "not implemented yet"); } } // end for. assert (changed && "nothing changed while lowering SUBx/ADDx"); VTList = DAG.getVTList(MVT::i8, MVT::Flag); if (N->getOpcode() == ASE) { // We must take in the existing carry // if this node is part of an existing subx/addx sequence. LoOps[2] = N->getOperand(2).getValue(1); as1 = DAG.getNode (ASE, VTList, LoOps, 3); } else { as1 = DAG.getNode (ASC, VTList, LoOps, 2); } HiOps[2] = as1.getValue(1); as2 = DAG.getNode (ASE, VTList, HiOps, 3); // We must build a pair that also provides the carry from sube/adde. OutOps[0] = as1; OutOps[1] = as2; OutOps[2] = as2.getValue(1); // Breaking an original i16, so lets make the Package also an i16. if (N->getOpcode() == ASE) { VTList = DAG.getVTList(MVT::i16, MVT::Flag); retVal = DAG.getNode (PIC16ISD::Package, VTList, OutOps, 3); DCI.CombineTo (N, retVal, OutOps[2]); } else if (N->getOpcode() == ASC) { VTList = DAG.getVTList(MVT::i16, MVT::Flag); retVal = DAG.getNode (PIC16ISD::Package, VTList, OutOps, 2); DCI.CombineTo (N, retVal, OutOps[2]); } else if (N->getOpcode() == AS) { VTList = DAG.getVTList(MVT::i16); retVal = DAG.getNode (PIC16ISD::Package, VTList, OutOps, 2); DCI.CombineTo (N, retVal); } return retVal; } //===----------------------------------------------------------------------===// // Calling Convention Implementation //===----------------------------------------------------------------------===// #include "PIC16GenCallingConv.inc" //===----------------------------------------------------------------------===// // CALL Calling Convention Implementation //===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===// // FORMAL_ARGUMENTS Calling Convention Implementation //===----------------------------------------------------------------------===// SDOperand PIC16TargetLowering:: LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG) { SmallVector ArgValues; SDOperand Root = Op.getOperand(0); // Return the new list of results. // FIXME: Just copy right now. ArgValues.push_back(Root); return DAG.getMergeValues(Op.Val->getVTList(), &ArgValues[0], ArgValues.size()).getValue(Op.ResNo); } //===----------------------------------------------------------------------===// // Return Value Calling Convention Implementation //===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===// // PIC16 Inline Assembly Support //===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===// // Target Optimization Hooks //===----------------------------------------------------------------------===// SDOperand PIC16TargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const { int i; ConstantSDNode *CST; SelectionDAG &DAG = DCI.DAG; switch (N->getOpcode()) { default: break; case PIC16ISD::Package: DOUT << "==== combining PIC16ISD::Package\n"; return SDOperand(); case ISD::ADD: case ISD::SUB: if ((N->getOperand(0).getOpcode() == ISD::GlobalAddress) || (N->getOperand(0).getOpcode() == ISD::FrameIndex)) { // Do not touch pointer adds. return SDOperand (); } break; case ISD::ADDE : case ISD::ADDC : case ISD::SUBE : case ISD::SUBC : if (N->getValueType(0) == MVT::i16) { SDOperand retVal = LowerADDSUB(N, DAG,DCI); // LowerADDSUB has already combined the result, // so we just return nothing to avoid assertion failure from llvm // if N has been deleted already. return SDOperand(); } else if (N->getValueType(0) == MVT::i8) { // Sanity check .... for (int i=0; i<2; i++) { if (N->getOperand (i).getOpcode() == PIC16ISD::Package) { assert (0 && "don't want to have PIC16ISD::Package as intput to add:i8"); } } } break; // FIXME: split this large chunk of code. case ISD::STORE : { SDOperand Chain = N->getOperand(0); SDOperand Src = N->getOperand(1); SDOperand Dest = N->getOperand(2); unsigned int DstOff = 0; int NUM_STORES = 0; SDOperand Stores[6]; // if source operand is expected to be extended to // some higher type then - remove this extension // SDNode and do the extension manually if ((Src.getOpcode() == ISD::ANY_EXTEND) || (Src.getOpcode() == ISD::SIGN_EXTEND) || (Src.getOpcode() == ISD::ZERO_EXTEND)) { Src = Src.Val->getOperand(0); Stores[0] = DAG.getStore(Chain, Src, Dest, NULL,0); return Stores[0]; } switch(Src.getValueType().getSimpleVT()) { default: assert(false && "Invalid value type!"); case MVT::i8: break; case MVT::i16: NUM_STORES = 2; break; case MVT::i32: NUM_STORES = 4; break; case MVT::i64: NUM_STORES = 8; break; } if (isa(Dest) && isa(Src) && (Src.getValueType() != MVT::i8)) { //create direct addressing a = b Chain = Src.getOperand(0); for (i=0; i(Dest) && isa(Src) && (Src.getValueType() != MVT::i8)) { //create direct addressing a = CONST CST = dyn_cast(Src); for (i = 0; i < NUM_STORES; i++) { SDOperand CNST = DAG.getConstant(CST->getValue() >> i*8, MVT::i8); SDOperand ADN = DAG.getNode(ISD::ADD, MVT::i16, Dest, DAG.getConstant(DstOff, MVT::i16)); Stores[i] = DAG.getStore(Chain, CNST, ADN, NULL, 0); Chain = Stores[i]; DstOff += 1; } Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, &Stores[0], i); return Chain; } else if (isa(Dest) && isa(Src) && (Src.getValueType() != MVT::i8)) { // Create indirect addressing. CST = dyn_cast(Src); Chain = Dest.getOperand(0); SDOperand Load; Load = DAG.getLoad(MVT::i16, Chain,Dest.getOperand(1), NULL, 0); Chain = Load.getValue(1); for (i=0; igetValue() >> i*8, MVT::i8); Stores[i] = DAG.getStore(Chain, CNST, Load, NULL, 0); Chain = Stores[i]; DstOff += 1; } Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, &Stores[0], i); return Chain; } else if (isa(Dest) && isa(Src)) { // GlobalAddressSDNode *GAD = dyn_cast(Src); return SDOperand(); } else if (Src.getOpcode() == PIC16ISD::Package) { StoreSDNode *st = dyn_cast(N); SDOperand toWorkList, retVal; Chain = N->getOperand(0); if (st->isTruncatingStore()) { retVal = DAG.getStore(Chain, Src.getOperand(0), Dest, NULL, 0); } else { toWorkList = DAG.getNode(ISD::ADD, MVT::i16, Dest, DAG.getConstant(1, MVT::i16)); Stores[1] = DAG.getStore(Chain, Src.getOperand(0), Dest, NULL, 0); Stores[0] = DAG.getStore(Chain, Src.getOperand(1), toWorkList, NULL, 0); // We want to merge sequence of add with constant to one add and a // constant, so add the ADD node to worklist to have llvm do that // automatically. DCI.AddToWorklist(toWorkList.Val); // We don't need the Package so add to worklist so llvm deletes it DCI.AddToWorklist(Src.Val); retVal = DAG.getNode(ISD::TokenFactor, MVT::Other, &Stores[0], 2); } return retVal; } else if (Src.getOpcode() == ISD::TRUNCATE) { } else { } } // end ISD::STORE. break; case ISD::LOAD : { SDOperand Ptr = N->getOperand(1); if (Ptr.getOpcode() == PIC16ISD::Package) { assert (0 && "not implemented yet"); } } break; } // end switch. return SDOperand(); } //===----------------------------------------------------------------------===// // Utility functions //===----------------------------------------------------------------------===// const SDOperand *PIC16TargetLowering:: findLoadi8(const SDOperand &Src, SelectionDAG &DAG) const { unsigned int i; if ((Src.getOpcode() == ISD::LOAD) && (Src.getValueType() == MVT::i8)) return &Src; for (i=0; i