SDValue WebAssemblyTargetLowering::LowerCopyToReg(SDValue Op, SelectionDAG &DAG) const { SDValue Src = Op.getOperand(2); if (isa<FrameIndexSDNode>(Src.getNode())) { // CopyToReg nodes don't support FrameIndex operands. Other targets select // the FI to some LEA-like instruction, but since we don't have that, we // need to insert some kind of instruction that can take an FI operand and // produces a value usable by CopyToReg (i.e. in a vreg). So insert a dummy // copy_local between Op and its FI operand. SDValue Chain = Op.getOperand(0); SDLoc DL(Op); unsigned Reg = cast<RegisterSDNode>(Op.getOperand(1))->getReg(); EVT VT = Src.getValueType(); SDValue Copy( DAG.getMachineNode(VT == MVT::i32 ? WebAssembly::COPY_LOCAL_I32 : WebAssembly::COPY_LOCAL_I64, DL, VT, Src), 0); return Op.getNode()->getNumValues() == 1 ? DAG.getCopyToReg(Chain, DL, Reg, Copy) : DAG.getCopyToReg(Chain, DL, Reg, Copy, Op.getNumOperands() == 4 ? Op.getOperand(3) : SDValue()); } return SDValue(); }
// Expansion of ADDE / SUBE. This is a bit involved since blackfin doesn't have // add-with-carry instructions. SDValue BlackfinTargetLowering::LowerADDE(SDValue Op, SelectionDAG &DAG) const { // Operands: lhs, rhs, carry-in (AC0 flag) // Results: sum, carry-out (AC0 flag) DebugLoc dl = Op.getDebugLoc(); unsigned Opcode = Op.getOpcode()==ISD::ADDE ? BF::ADD : BF::SUB; // zext incoming carry flag in AC0 to 32 bits SDNode* CarryIn = DAG.getMachineNode(BF::MOVE_cc_ac0, dl, MVT::i32, /* flag= */ Op.getOperand(2)); CarryIn = DAG.getMachineNode(BF::MOVECC_zext, dl, MVT::i32, SDValue(CarryIn, 0)); // Add operands, produce sum and carry flag SDNode *Sum = DAG.getMachineNode(Opcode, dl, MVT::i32, MVT::Glue, Op.getOperand(0), Op.getOperand(1)); // Store intermediate carry from Sum SDNode* Carry1 = DAG.getMachineNode(BF::MOVE_cc_ac0, dl, MVT::i32, /* flag= */ SDValue(Sum, 1)); // Add incoming carry, again producing an output flag Sum = DAG.getMachineNode(Opcode, dl, MVT::i32, MVT::Glue, SDValue(Sum, 0), SDValue(CarryIn, 0)); // Update AC0 with the intermediate carry, producing a flag. SDNode *CarryOut = DAG.getMachineNode(BF::OR_ac0_cc, dl, MVT::Glue, SDValue(Carry1, 0)); // Compose (i32, flag) pair SDValue ops[2] = { SDValue(Sum, 0), SDValue(CarryOut, 0) }; return DAG.getMergeValues(ops, 2, dl); }
// After instruction selection, insert COPY_TO_REGCLASS nodes to help in // choosing the proper register classes. void BlackfinDAGToDAGISel::FixRegisterClasses(SelectionDAG &DAG) { const BlackfinInstrInfo &TII = getInstrInfo(); const BlackfinRegisterInfo *TRI = getRegisterInfo(); DAG.AssignTopologicalOrder(); HandleSDNode Dummy(DAG.getRoot()); for (SelectionDAG::allnodes_iterator NI = DAG.allnodes_begin(); NI != DAG.allnodes_end(); ++NI) { if (NI->use_empty() || !NI->isMachineOpcode()) continue; const TargetInstrDesc &DefTID = 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()) continue; const TargetRegisterClass *DefRC = DefTID.OpInfo[UI.getUse().getResNo()].getRegClass(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); if (!DefRC || !UseRC) continue; // We cannot copy CC <-> !(CC/D) if ((isCC(DefRC) && !isDCC(UseRC)) || (isCC(UseRC) && !isDCC(DefRC))) { SDNode *Copy = DAG.getMachineNode(TargetOpcode::COPY_TO_REGCLASS, NI->getDebugLoc(), MVT::i32, UI.getUse().get(), DAG.getTargetConstant(BF::DRegClassID, MVT::i32)); UpdateNodeOperand(DAG, *UI, UI.getOperandNo(), SDValue(Copy, 0)); } } } DAG.setRoot(Dummy.getValue()); }