// Match memory operand of the form [reg], [imm+reg], and [reg+imm] bool PTXDAGToDAGISel::SelectADDRri(SDValue &Addr, SDValue &Base, SDValue &Offset) { if (Addr.getOpcode() != ISD::ADD) { // let SelectADDRii handle the [imm] case if (isImm(Addr)) return false; // it is [reg] Base = Addr; Offset = CurDAG->getTargetConstant(0, MVT::i32); return true; } if (Addr.getNumOperands() < 2) return false; // let SelectADDRii handle the [imm+imm] case if (isImm(Addr.getOperand(0)) && isImm(Addr.getOperand(1))) return false; // try [reg+imm] and [imm+reg] for (int i = 0; i < 2; i ++) if (SelectImm(Addr.getOperand(1-i), Offset)) { Base = Addr.getOperand(i); return true; } // neither [reg+imm] nor [imm+reg] return false; }
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(); }
// Match memory operand of the form [reg+reg] bool PTXDAGToDAGISel::SelectADDRrr(SDValue &Addr, SDValue &R1, SDValue &R2) { if (Addr.getOpcode() != ISD::ADD || Addr.getNumOperands() < 2 || isImm(Addr.getOperand(0)) || isImm(Addr.getOperand(1))) return false; R1 = Addr; R2 = CurDAG->getTargetConstant(0, MVT::i32); return true; }
// Match memory operand of the form [reg+reg] bool PTXDAGToDAGISel::SelectADDRrr(SDValue &Addr, SDValue &R1, SDValue &R2) { if (Addr.getOpcode() != ISD::ADD || Addr.getNumOperands() < 2 || isImm(Addr.getOperand(0)) || isImm(Addr.getOperand(1))) return false; assert(Addr.getValueType().isSimple() && "Type must be simple"); R1 = Addr; R2 = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT()); return true; }
// This function expands mips intrinsic nodes which have 64-bit input operands // or output values. // // out64 = intrinsic-node in64 // => // lo = copy (extract-element (in64, 0)) // hi = copy (extract-element (in64, 1)) // mips-specific-node // v0 = copy lo // v1 = copy hi // out64 = merge-values (v0, v1) // static SDValue lowerDSPIntr(SDValue Op, SelectionDAG &DAG, unsigned Opc) { DebugLoc DL = Op.getDebugLoc(); bool HasChainIn = Op->getOperand(0).getValueType() == MVT::Other; SmallVector<SDValue, 3> Ops; unsigned OpNo = 0; // See if Op has a chain input. if (HasChainIn) Ops.push_back(Op->getOperand(OpNo++)); // The next operand is the intrinsic opcode. assert(Op->getOperand(OpNo).getOpcode() == ISD::TargetConstant); // See if the next operand has type i64. SDValue Opnd = Op->getOperand(++OpNo), In64; if (Opnd.getValueType() == MVT::i64) In64 = initAccumulator(Opnd, DL, DAG); else Ops.push_back(Opnd); // Push the remaining operands. for (++OpNo ; OpNo < Op->getNumOperands(); ++OpNo) Ops.push_back(Op->getOperand(OpNo)); // Add In64 to the end of the list. if (In64.getNode()) Ops.push_back(In64); // Scan output. SmallVector<EVT, 2> ResTys; for (SDNode::value_iterator I = Op->value_begin(), E = Op->value_end(); I != E; ++I) ResTys.push_back((*I == MVT::i64) ? MVT::Untyped : *I); // Create node. SDValue Val = DAG.getNode(Opc, DL, ResTys, &Ops[0], Ops.size()); SDValue Out = (ResTys[0] == MVT::Untyped) ? extractLOHI(Val, DL, DAG) : Val; if (!HasChainIn) return Out; assert(Val->getValueType(1) == MVT::Other); SDValue Vals[] = { Out, SDValue(Val.getNode(), 1) }; return DAG.getMergeValues(Vals, 2, DL); }
/// Given a chain return a new chain where any appearance of Old is replaced /// by New. There must be at most one instruction between Old and Chain and /// this instruction must be a TokenFactor. Returns an empty SDValue if /// these conditions don't hold. static SDValue replaceInChain(SelectionDAG *CurDAG, SDValue Chain, SDValue Old, SDValue New) { if (Chain == Old) return New; if (Chain->getOpcode() != ISD::TokenFactor) return SDValue(); SmallVector<SDValue, 8> Ops; bool found = false; for (unsigned i = 0, e = Chain->getNumOperands(); i != e; ++i) { if (Chain->getOperand(i) == Old) { Ops.push_back(New); found = true; } else { Ops.push_back(Chain->getOperand(i)); } } if (!found) return SDValue(); return CurDAG->getNode(ISD::TokenFactor, SDLoc(Chain), MVT::Other, Ops); }
SDValue AMDGPUTargetLowering::LowerBUILD_VECTOR( SDValue Op, SelectionDAG &DAG ) const { EVT VT = Op.getValueType(); SDValue Nodes1; SDValue second; SDValue third; SDValue fourth; DebugLoc DL = Op.getDebugLoc(); Nodes1 = DAG.getNode(AMDGPUISD::VBUILD, DL, VT, Op.getOperand(0)); #if 0 bool allEqual = true; for (unsigned x = 1, y = Op.getNumOperands(); x < y; ++x) { if (Op.getOperand(0) != Op.getOperand(x)) { allEqual = false; break; } } if (allEqual) { return Nodes1; } #endif switch(Op.getNumOperands()) { default: case 1: break; case 4: fourth = Op.getOperand(3); if (fourth.getOpcode() != ISD::UNDEF) { Nodes1 = DAG.getNode( ISD::INSERT_VECTOR_ELT, DL, Op.getValueType(), Nodes1, fourth, DAG.getConstant(7, MVT::i32)); } case 3: third = Op.getOperand(2); if (third.getOpcode() != ISD::UNDEF) { Nodes1 = DAG.getNode( ISD::INSERT_VECTOR_ELT, DL, Op.getValueType(), Nodes1, third, DAG.getConstant(6, MVT::i32)); } case 2: second = Op.getOperand(1); if (second.getOpcode() != ISD::UNDEF) { Nodes1 = DAG.getNode( ISD::INSERT_VECTOR_ELT, DL, Op.getValueType(), Nodes1, second, DAG.getConstant(5, MVT::i32)); } break; }; return Nodes1; }
SDValue IA64TargetLowering:: LowerOperation(SDValue Op, SelectionDAG &DAG) { switch (Op.getOpcode()) { default: assert(0 && "Should not custom lower this!"); case ISD::GlobalTLSAddress: assert(0 && "TLS not implemented for IA64."); case ISD::RET: { SDValue AR_PFSVal, Copy; switch(Op.getNumOperands()) { default: assert(0 && "Do not know how to return this many arguments!"); abort(); case 1: AR_PFSVal = DAG.getCopyFromReg(Op.getOperand(0), VirtGPR, MVT::i64); AR_PFSVal = DAG.getCopyToReg(AR_PFSVal.getValue(1), IA64::AR_PFS, AR_PFSVal); return DAG.getNode(IA64ISD::RET_FLAG, MVT::Other, AR_PFSVal); case 3: { // Copy the result into the output register & restore ar.pfs MVT ArgVT = Op.getOperand(1).getValueType(); unsigned ArgReg = ArgVT.isInteger() ? IA64::r8 : IA64::F8; AR_PFSVal = DAG.getCopyFromReg(Op.getOperand(0), VirtGPR, MVT::i64); Copy = DAG.getCopyToReg(AR_PFSVal.getValue(1), ArgReg, Op.getOperand(1), SDValue()); AR_PFSVal = DAG.getCopyToReg(Copy.getValue(0), IA64::AR_PFS, AR_PFSVal, Copy.getValue(1)); return DAG.getNode(IA64ISD::RET_FLAG, MVT::Other, AR_PFSVal, AR_PFSVal.getValue(1)); } } return SDValue(); } case ISD::VAARG: { MVT VT = getPointerTy(); const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue(); SDValue VAList = DAG.getLoad(VT, Op.getOperand(0), Op.getOperand(1), SV, 0); // Increment the pointer, VAList, to the next vaarg SDValue VAIncr = DAG.getNode(ISD::ADD, VT, VAList, DAG.getConstant(VT.getSizeInBits()/8, VT)); // Store the incremented VAList to the legalized pointer VAIncr = DAG.getStore(VAList.getValue(1), VAIncr, Op.getOperand(1), SV, 0); // Load the actual argument out of the pointer VAList return DAG.getLoad(Op.getValueType(), VAIncr, VAList, NULL, 0); } case ISD::VASTART: { // vastart just stores the address of the VarArgsFrameIndex slot into the // memory location argument. SDValue FR = DAG.getFrameIndex(VarArgsFrameIndex, MVT::i64); const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue(); return DAG.getStore(Op.getOperand(0), FR, Op.getOperand(1), SV, 0); } // Frame & Return address. Currently unimplemented case ISD::RETURNADDR: break; case ISD::FRAMEADDR: break; } return SDValue(); }