// ComplexPattern used on BPF Load/Store instructions bool BPFDAGToDAGISel::SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset) { // if Address is FI, get the TargetFrameIndex. SDLoc DL(Addr); if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64); Offset = CurDAG->getTargetConstant(0, DL, MVT::i64); return true; } if (Addr.getOpcode() == ISD::TargetExternalSymbol || Addr.getOpcode() == ISD::TargetGlobalAddress) return false; // Addresses of the form Addr+const or Addr|const if (CurDAG->isBaseWithConstantOffset(Addr)) { ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)); if (isInt<16>(CN->getSExtValue())) { // If the first operand is a FI, get the TargetFI Node if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64); else Base = Addr.getOperand(0); Offset = CurDAG->getTargetConstant(CN->getSExtValue(), DL, MVT::i64); return true; } } Base = Addr; Offset = CurDAG->getTargetConstant(0, DL, MVT::i64); return true; }
/// ComplexPattern used on Cpu0InstrInfo /// Used on Cpu0 Load/Store instructions bool Cpu0DAGToDAGISel:: SelectAddr(SDNode *Parent, SDValue Addr, SDValue &Base, SDValue &Offset) { EVT ValTy = Addr.getValueType(); // If Parent is an unaligned f32 load or store, select a (base + index) // floating point load/store instruction (luxc1 or suxc1). const LSBaseSDNode* LS = 0; if (Parent && (LS = dyn_cast<LSBaseSDNode>(Parent))) { EVT VT = LS->getMemoryVT(); if (VT.getSizeInBits() / 8 > LS->getAlignment()) { assert(TLI.allowsUnalignedMemoryAccesses(VT) && "Unaligned loads/stores not supported for this type."); if (VT == MVT::f32) return false; } } // if Address is FI, get the TargetFrameIndex. if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy); Offset = CurDAG->getTargetConstant(0, ValTy); return true; } // on PIC code Load GA if (Addr.getOpcode() == Cpu0ISD::Wrapper) { Base = Addr.getOperand(0); Offset = Addr.getOperand(1); return true; } if (TM.getRelocationModel() != Reloc::PIC_) { if ((Addr.getOpcode() == ISD::TargetExternalSymbol || Addr.getOpcode() == ISD::TargetGlobalAddress)) return false; } // Addresses of the form FI+const or FI|const if (CurDAG->isBaseWithConstantOffset(Addr)) { ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)); if (isInt<16>(CN->getSExtValue())) { // If the first operand is a FI, get the TargetFI Node if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode> (Addr.getOperand(0))) Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy); else Base = Addr.getOperand(0); Offset = CurDAG->getTargetConstant(CN->getZExtValue(), ValTy); return true; } } Base = Addr; Offset = CurDAG->getTargetConstant(0, ValTy); return true; }
/// Select multiply instructions. SDNode* CoffeeDAGToDAGISel::SelectMULT(SDNode *N, DebugLoc dl) { ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N->getOperand(1)); unsigned Opc = 0; if (CN) { // signed 15 bit imm bool test = isInt<15>(CN->getSExtValue()); bool test1 = isInt<32>(CN->getSExtValue()); if (isInt<15>(CN->getSExtValue())) Opc = Coffee::MULTI; else Opc = Coffee::MULTR; } else { // register Opc = Coffee::MULTR; } if (Opc == 0 ) llvm_unreachable("coffee: selectMULT"); SDNode *Mul = CurDAG->getMachineNode(Opc, dl, MVT::i32, MVT::Glue, N->getOperand(0), N->getOperand(1)); // take the second output which is glue SDValue glue = SDValue(Mul, 1); /* def MULHI : InstCoffee<(outs GPRC:$rd), (ins), "mulhi\t$rd", [], IIAlu, FrmJ> { }*/ // this MULHI instruction is meant for telling which register is used to save the upper half of the // mulitplication result so no inputs are needed here. // but we need to take the glue output from MULTI/MULTR so that it will guarantee the MULHI will appear // right after them. return CurDAG->getMachineNode(Coffee::MULHI, dl, MVT::i32, glue); }
bool XCoreDAGToDAGISel::SelectADDRcpii(SDValue Op, SDValue Addr, SDValue &Base, SDValue &Offset) { if (Addr.getOpcode() == XCoreISD::CPRelativeWrapper) { Base = Addr.getOperand(0); Offset = CurDAG->getTargetConstant(0, MVT::i32); return true; } if (Addr.getOpcode() == ISD::ADD) { ConstantSDNode *CN = 0; if ((Addr.getOperand(0).getOpcode() == XCoreISD::CPRelativeWrapper) && (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) && (CN->getSExtValue() % 4 == 0)) { // Constant word offset from a object in the data region Base = Addr.getOperand(0).getOperand(0); Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32); return true; } } return false; }
bool XCoreDAGToDAGISel::SelectADDRspii(SDValue Addr, SDValue &Base, SDValue &Offset) { FrameIndexSDNode *FIN = 0; if ((FIN = dyn_cast<FrameIndexSDNode>(Addr))) { Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); Offset = CurDAG->getTargetConstant(0, MVT::i32); return true; } if (Addr.getOpcode() == ISD::ADD) { ConstantSDNode *CN = 0; if ((FIN = dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) && (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) && (CN->getSExtValue() % 4 == 0 && CN->getSExtValue() >= 0)) { // Constant positive word offset from frame index Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32); return true; } } return false; }
// ComplexPattern used on BPF FI instruction bool BPFDAGToDAGISel::SelectFIAddr(SDValue Addr, SDValue &Base, SDValue &Offset) { SDLoc DL(Addr); if (!CurDAG->isBaseWithConstantOffset(Addr)) return false; // Addresses of the form Addr+const or Addr|const ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)); if (isInt<16>(CN->getSExtValue())) { // If the first operand is a FI, get the TargetFI Node if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64); else return false; Offset = CurDAG->getTargetConstant(CN->getSExtValue(), DL, MVT::i64); return true; } return false; }
/// Match frameindex+offset and frameindex|offset bool MipsSEDAGToDAGISel::selectAddrFrameIndexOffset(SDValue Addr, SDValue &Base, SDValue &Offset, unsigned OffsetBits) const { if (CurDAG->isBaseWithConstantOffset(Addr)) { ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)); if (isIntN(OffsetBits, CN->getSExtValue())) { EVT ValTy = Addr.getValueType(); // If the first operand is a FI, get the TargetFI Node if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode> (Addr.getOperand(0))) Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy); else Base = Addr.getOperand(0); Offset = CurDAG->getTargetConstant(CN->getZExtValue(), ValTy); return true; } } return false; }
/// Used on microMIPS Load/Store unaligned instructions (12-bit offset) bool MipsSEDAGToDAGISel::selectAddrRegImm12(SDValue Addr, SDValue &Base, SDValue &Offset) const { EVT ValTy = Addr.getValueType(); // Addresses of the form FI+const or FI|const if (CurDAG->isBaseWithConstantOffset(Addr)) { ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)); if (isInt<12>(CN->getSExtValue())) { // If the first operand is a FI then get the TargetFI Node if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode> (Addr.getOperand(0))) Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy); else Base = Addr.getOperand(0); Offset = CurDAG->getTargetConstant(CN->getZExtValue(), ValTy); return true; } } return false; }
/// ComplexPattern used on MipsInstrInfo /// Used on Mips Load/Store instructions bool MipsSEDAGToDAGISel::selectAddrRegImm(SDValue Addr, SDValue &Base, SDValue &Offset) const { EVT ValTy = Addr.getValueType(); // if Address is FI, get the TargetFrameIndex. if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy); Offset = CurDAG->getTargetConstant(0, ValTy); return true; } // on PIC code Load GA if (Addr.getOpcode() == MipsISD::Wrapper) { Base = Addr.getOperand(0); Offset = Addr.getOperand(1); return true; } if (TM.getRelocationModel() != Reloc::PIC_) { if ((Addr.getOpcode() == ISD::TargetExternalSymbol || Addr.getOpcode() == ISD::TargetGlobalAddress)) return false; } // Addresses of the form FI+const or FI|const if (CurDAG->isBaseWithConstantOffset(Addr)) { ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)); if (isInt<16>(CN->getSExtValue())) { // If the first operand is a FI, get the TargetFI Node if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode> (Addr.getOperand(0))) Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy); else Base = Addr.getOperand(0); Offset = CurDAG->getTargetConstant(CN->getZExtValue(), ValTy); return true; } } // Operand is a result from an ADD. if (Addr.getOpcode() == ISD::ADD) { // When loading from constant pools, load the lower address part in // the instruction itself. Example, instead of: // lui $2, %hi($CPI1_0) // addiu $2, $2, %lo($CPI1_0) // lwc1 $f0, 0($2) // Generate: // lui $2, %hi($CPI1_0) // lwc1 $f0, %lo($CPI1_0)($2) if (Addr.getOperand(1).getOpcode() == MipsISD::Lo || Addr.getOperand(1).getOpcode() == MipsISD::GPRel) { SDValue Opnd0 = Addr.getOperand(1).getOperand(0); if (isa<ConstantPoolSDNode>(Opnd0) || isa<GlobalAddressSDNode>(Opnd0) || isa<JumpTableSDNode>(Opnd0)) { Base = Addr.getOperand(0); Offset = Opnd0; return true; } } } return false; }
bool Mips16DAGToDAGISel::selectAddr16( SDNode *Parent, SDValue Addr, SDValue &Base, SDValue &Offset, SDValue &Alias) { EVT ValTy = Addr.getValueType(); Alias = CurDAG->getTargetConstant(0, ValTy); // if Address is FI, get the TargetFrameIndex. if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy); Offset = CurDAG->getTargetConstant(0, ValTy); getMips16SPRefReg(Parent, Alias); return true; } // on PIC code Load GA if (Addr.getOpcode() == MipsISD::Wrapper) { Base = Addr.getOperand(0); Offset = Addr.getOperand(1); return true; } if (TM.getRelocationModel() != Reloc::PIC_) { if ((Addr.getOpcode() == ISD::TargetExternalSymbol || Addr.getOpcode() == ISD::TargetGlobalAddress)) return false; } // Addresses of the form FI+const or FI|const if (CurDAG->isBaseWithConstantOffset(Addr)) { ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)); if (isInt<16>(CN->getSExtValue())) { // If the first operand is a FI, get the TargetFI Node if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode> (Addr.getOperand(0))) { Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy); getMips16SPRefReg(Parent, Alias); } else Base = Addr.getOperand(0); Offset = CurDAG->getTargetConstant(CN->getZExtValue(), ValTy); return true; } } // Operand is a result from an ADD. if (Addr.getOpcode() == ISD::ADD) { // When loading from constant pools, load the lower address part in // the instruction itself. Example, instead of: // lui $2, %hi($CPI1_0) // addiu $2, $2, %lo($CPI1_0) // lwc1 $f0, 0($2) // Generate: // lui $2, %hi($CPI1_0) // lwc1 $f0, %lo($CPI1_0)($2) if (Addr.getOperand(1).getOpcode() == MipsISD::Lo || Addr.getOperand(1).getOpcode() == MipsISD::GPRel) { SDValue Opnd0 = Addr.getOperand(1).getOperand(0); if (isa<ConstantPoolSDNode>(Opnd0) || isa<GlobalAddressSDNode>(Opnd0) || isa<JumpTableSDNode>(Opnd0)) { Base = Addr.getOperand(0); Offset = Opnd0; return true; } } // If an indexed floating point load/store can be emitted, return false. const LSBaseSDNode *LS = dyn_cast<LSBaseSDNode>(Parent); if (LS && (LS->getMemoryVT() == MVT::f32 || LS->getMemoryVT() == MVT::f64) && Subtarget.hasFPIdx()) return false; } Base = Addr; Offset = CurDAG->getTargetConstant(0, ValTy); return true; }
SDValue LanaiTargetLowering::LowerMUL(SDValue Op, SelectionDAG &DAG) const { EVT VT = Op->getValueType(0); if (VT != MVT::i32) return SDValue(); ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op->getOperand(1)); if (!C) return SDValue(); int64_t MulAmt = C->getSExtValue(); int32_t HighestOne = -1; uint32_t NonzeroEntries = 0; int SignedDigit[32] = {0}; // Convert to non-adjacent form (NAF) signed-digit representation. // NAF is a signed-digit form where no adjacent digits are non-zero. It is the // minimal Hamming weight representation of a number (on average 1/3 of the // digits will be non-zero vs 1/2 for regular binary representation). And as // the non-zero digits will be the only digits contributing to the instruction // count, this is desirable. The next loop converts it to NAF (following the // approach in 'Guide to Elliptic Curve Cryptography' [ISBN: 038795273X]) by // choosing the non-zero coefficients such that the resulting quotient is // divisible by 2 which will cause the next coefficient to be zero. int64_t E = std::abs(MulAmt); int S = (MulAmt < 0 ? -1 : 1); int I = 0; while (E > 0) { int ZI = 0; if (E % 2 == 1) { ZI = 2 - (E % 4); if (ZI != 0) ++NonzeroEntries; } SignedDigit[I] = S * ZI; if (SignedDigit[I] == 1) HighestOne = I; E = (E - ZI) / 2; ++I; } // Compute number of instructions required. Due to differences in lowering // between the different processors this count is not exact. // Start by assuming a shift and a add/sub for every non-zero entry (hence // every non-zero entry requires 1 shift and 1 add/sub except for the first // entry). int32_t InstrRequired = 2 * NonzeroEntries - 1; // Correct possible over-adding due to shift by 0 (which is not emitted). if (std::abs(MulAmt) % 2 == 1) --InstrRequired; // Return if the form generated would exceed the instruction threshold. if (InstrRequired > LanaiLowerConstantMulThreshold) return SDValue(); SDValue Res; SDLoc DL(Op); SDValue V = Op->getOperand(0); // Initialize the running sum. Set the running sum to the maximal shifted // positive value (i.e., largest i such that zi == 1 and MulAmt has V<<i as a // term NAF). if (HighestOne == -1) Res = DAG.getConstant(0, DL, MVT::i32); else { Res = DAG.getNode(ISD::SHL, DL, VT, V, DAG.getConstant(HighestOne, DL, MVT::i32)); SignedDigit[HighestOne] = 0; } // Assemble multiplication from shift, add, sub using NAF form and running // sum. for (unsigned int I = 0; I < sizeof(SignedDigit) / sizeof(SignedDigit[0]); ++I) { if (SignedDigit[I] == 0) continue; // Shifted multiplicand (v<<i). SDValue Op = DAG.getNode(ISD::SHL, DL, VT, V, DAG.getConstant(I, DL, MVT::i32)); if (SignedDigit[I] == 1) Res = DAG.getNode(ISD::ADD, DL, VT, Res, Op); else if (SignedDigit[I] == -1) Res = DAG.getNode(ISD::SUB, DL, VT, Res, Op); } return Res; }
/*! */ SDNode * SPUDAGToDAGISel::Select(SDNode *N) { unsigned Opc = N->getOpcode(); int n_ops = -1; unsigned NewOpc = 0; EVT OpVT = N->getValueType(0); SDValue Ops[8]; DebugLoc dl = N->getDebugLoc(); if (N->isMachineOpcode()) return NULL; // Already selected. if (Opc == ISD::FrameIndex) { int FI = cast<FrameIndexSDNode>(N)->getIndex(); SDValue TFI = CurDAG->getTargetFrameIndex(FI, N->getValueType(0)); SDValue Imm0 = CurDAG->getTargetConstant(0, N->getValueType(0)); if (FI < 128) { NewOpc = SPU::AIr32; Ops[0] = TFI; Ops[1] = Imm0; n_ops = 2; } else { NewOpc = SPU::Ar32; Ops[0] = CurDAG->getRegister(SPU::R1, N->getValueType(0)); Ops[1] = SDValue(CurDAG->getMachineNode(SPU::ILAr32, dl, N->getValueType(0), TFI), 0); n_ops = 2; } } else if (Opc == ISD::Constant && OpVT == MVT::i64) { // Catch the i64 constants that end up here. Note: The backend doesn't // attempt to legalize the constant (it's useless because DAGCombiner // will insert 64-bit constants and we can't stop it). return SelectI64Constant(N, OpVT, N->getDebugLoc()); } else if ((Opc == ISD::ZERO_EXTEND || Opc == ISD::ANY_EXTEND) && OpVT == MVT::i64) { SDValue Op0 = N->getOperand(0); EVT Op0VT = Op0.getValueType(); EVT Op0VecVT = EVT::getVectorVT(*CurDAG->getContext(), Op0VT, (128 / Op0VT.getSizeInBits())); EVT OpVecVT = EVT::getVectorVT(*CurDAG->getContext(), OpVT, (128 / OpVT.getSizeInBits())); SDValue shufMask; switch (Op0VT.getSimpleVT().SimpleTy) { default: report_fatal_error("CellSPU Select: Unhandled zero/any extend EVT"); /*NOTREACHED*/ case MVT::i32: shufMask = CurDAG->getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32, CurDAG->getConstant(0x80808080, MVT::i32), CurDAG->getConstant(0x00010203, MVT::i32), CurDAG->getConstant(0x80808080, MVT::i32), CurDAG->getConstant(0x08090a0b, MVT::i32)); break; case MVT::i16: shufMask = CurDAG->getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32, CurDAG->getConstant(0x80808080, MVT::i32), CurDAG->getConstant(0x80800203, MVT::i32), CurDAG->getConstant(0x80808080, MVT::i32), CurDAG->getConstant(0x80800a0b, MVT::i32)); break; case MVT::i8: shufMask = CurDAG->getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32, CurDAG->getConstant(0x80808080, MVT::i32), CurDAG->getConstant(0x80808003, MVT::i32), CurDAG->getConstant(0x80808080, MVT::i32), CurDAG->getConstant(0x8080800b, MVT::i32)); break; } SDNode *shufMaskLoad = emitBuildVector(shufMask.getNode()); HandleSDNode PromoteScalar(CurDAG->getNode(SPUISD::PREFSLOT2VEC, dl, Op0VecVT, Op0)); SDValue PromScalar; if (SDNode *N = SelectCode(PromoteScalar.getValue().getNode())) PromScalar = SDValue(N, 0); else PromScalar = PromoteScalar.getValue(); SDValue zextShuffle = CurDAG->getNode(SPUISD::SHUFB, dl, OpVecVT, PromScalar, PromScalar, SDValue(shufMaskLoad, 0)); HandleSDNode Dummy2(zextShuffle); if (SDNode *N = SelectCode(Dummy2.getValue().getNode())) zextShuffle = SDValue(N, 0); else zextShuffle = Dummy2.getValue(); HandleSDNode Dummy(CurDAG->getNode(SPUISD::VEC2PREFSLOT, dl, OpVT, zextShuffle)); CurDAG->ReplaceAllUsesWith(N, Dummy.getValue().getNode()); SelectCode(Dummy.getValue().getNode()); return Dummy.getValue().getNode(); } else if (Opc == ISD::ADD && (OpVT == MVT::i64 || OpVT == MVT::v2i64)) { SDNode *CGLoad = emitBuildVector(getCarryGenerateShufMask(*CurDAG, dl).getNode()); HandleSDNode Dummy(CurDAG->getNode(SPUISD::ADD64_MARKER, dl, OpVT, N->getOperand(0), N->getOperand(1), SDValue(CGLoad, 0))); CurDAG->ReplaceAllUsesWith(N, Dummy.getValue().getNode()); if (SDNode *N = SelectCode(Dummy.getValue().getNode())) return N; return Dummy.getValue().getNode(); } else if (Opc == ISD::SUB && (OpVT == MVT::i64 || OpVT == MVT::v2i64)) { SDNode *CGLoad = emitBuildVector(getBorrowGenerateShufMask(*CurDAG, dl).getNode()); HandleSDNode Dummy(CurDAG->getNode(SPUISD::SUB64_MARKER, dl, OpVT, N->getOperand(0), N->getOperand(1), SDValue(CGLoad, 0))); CurDAG->ReplaceAllUsesWith(N, Dummy.getValue().getNode()); if (SDNode *N = SelectCode(Dummy.getValue().getNode())) return N; return Dummy.getValue().getNode(); } else if (Opc == ISD::MUL && (OpVT == MVT::i64 || OpVT == MVT::v2i64)) { SDNode *CGLoad = emitBuildVector(getCarryGenerateShufMask(*CurDAG, dl).getNode()); HandleSDNode Dummy(CurDAG->getNode(SPUISD::MUL64_MARKER, dl, OpVT, N->getOperand(0), N->getOperand(1), SDValue(CGLoad, 0))); CurDAG->ReplaceAllUsesWith(N, Dummy.getValue().getNode()); if (SDNode *N = SelectCode(Dummy.getValue().getNode())) return N; return Dummy.getValue().getNode(); } else if (Opc == ISD::TRUNCATE) { SDValue Op0 = N->getOperand(0); if ((Op0.getOpcode() == ISD::SRA || Op0.getOpcode() == ISD::SRL) && OpVT == MVT::i32 && Op0.getValueType() == MVT::i64) { // Catch (truncate:i32 ([sra|srl]:i64 arg, c), where c >= 32 // // Take advantage of the fact that the upper 32 bits are in the // i32 preferred slot and avoid shuffle gymnastics: ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Op0.getOperand(1)); if (CN != 0) { unsigned shift_amt = unsigned(CN->getZExtValue()); if (shift_amt >= 32) { SDNode *hi32 = CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS, dl, OpVT, Op0.getOperand(0), getRC(MVT::i32)); shift_amt -= 32; if (shift_amt > 0) { // Take care of the additional shift, if present: SDValue shift = CurDAG->getTargetConstant(shift_amt, MVT::i32); unsigned Opc = SPU::ROTMAIr32_i32; if (Op0.getOpcode() == ISD::SRL) Opc = SPU::ROTMr32; hi32 = CurDAG->getMachineNode(Opc, dl, OpVT, SDValue(hi32, 0), shift); } return hi32; } } } } else if (Opc == ISD::SHL) { if (OpVT == MVT::i64) return SelectSHLi64(N, OpVT); } else if (Opc == ISD::SRL) { if (OpVT == MVT::i64) return SelectSRLi64(N, OpVT); } else if (Opc == ISD::SRA) { if (OpVT == MVT::i64) return SelectSRAi64(N, OpVT); } else if (Opc == ISD::FNEG && (OpVT == MVT::f64 || OpVT == MVT::v2f64)) { DebugLoc dl = N->getDebugLoc(); // Check if the pattern is a special form of DFNMS: // (fneg (fsub (fmul R64FP:$rA, R64FP:$rB), R64FP:$rC)) SDValue Op0 = N->getOperand(0); if (Op0.getOpcode() == ISD::FSUB) { SDValue Op00 = Op0.getOperand(0); if (Op00.getOpcode() == ISD::FMUL) { unsigned Opc = SPU::DFNMSf64; if (OpVT == MVT::v2f64) Opc = SPU::DFNMSv2f64; return CurDAG->getMachineNode(Opc, dl, OpVT, Op00.getOperand(0), Op00.getOperand(1), Op0.getOperand(1)); } } SDValue negConst = CurDAG->getConstant(0x8000000000000000ULL, MVT::i64); SDNode *signMask = 0; unsigned Opc = SPU::XORfneg64; if (OpVT == MVT::f64) { signMask = SelectI64Constant(negConst.getNode(), MVT::i64, dl); } else if (OpVT == MVT::v2f64) { Opc = SPU::XORfnegvec; signMask = emitBuildVector(CurDAG->getNode(ISD::BUILD_VECTOR, dl, MVT::v2i64, negConst, negConst).getNode()); } return CurDAG->getMachineNode(Opc, dl, OpVT, N->getOperand(0), SDValue(signMask, 0)); } else if (Opc == ISD::FABS) { if (OpVT == MVT::f64) { SDNode *signMask = SelectI64Constant(0x7fffffffffffffffULL, MVT::i64, dl); return CurDAG->getMachineNode(SPU::ANDfabs64, dl, OpVT, N->getOperand(0), SDValue(signMask, 0)); } else if (OpVT == MVT::v2f64) { SDValue absConst = CurDAG->getConstant(0x7fffffffffffffffULL, MVT::i64); SDValue absVec = CurDAG->getNode(ISD::BUILD_VECTOR, dl, MVT::v2i64, absConst, absConst); SDNode *signMask = emitBuildVector(absVec.getNode()); return CurDAG->getMachineNode(SPU::ANDfabsvec, dl, OpVT, N->getOperand(0), SDValue(signMask, 0)); } } else if (Opc == SPUISD::LDRESULT) { // Custom select instructions for LDRESULT EVT VT = N->getValueType(0); SDValue Arg = N->getOperand(0); SDValue Chain = N->getOperand(1); SDNode *Result; Result = CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS, dl, VT, MVT::Other, Arg, getRC( VT.getSimpleVT()), Chain); return Result; } else if (Opc == SPUISD::IndirectAddr) { // Look at the operands: SelectCode() will catch the cases that aren't // specifically handled here. // // SPUInstrInfo catches the following patterns: // (SPUindirect (SPUhi ...), (SPUlo ...)) // (SPUindirect $sp, imm) EVT VT = N->getValueType(0); SDValue Op0 = N->getOperand(0); SDValue Op1 = N->getOperand(1); RegisterSDNode *RN; if ((Op0.getOpcode() != SPUISD::Hi && Op1.getOpcode() != SPUISD::Lo) || (Op0.getOpcode() == ISD::Register && ((RN = dyn_cast<RegisterSDNode>(Op0.getNode())) != 0 && RN->getReg() != SPU::R1))) { NewOpc = SPU::Ar32; Ops[1] = Op1; if (Op1.getOpcode() == ISD::Constant) { ConstantSDNode *CN = cast<ConstantSDNode>(Op1); Op1 = CurDAG->getTargetConstant(CN->getSExtValue(), VT); if (isInt<10>(CN->getSExtValue())) { NewOpc = SPU::AIr32; Ops[1] = Op1; } else { Ops[1] = SDValue(CurDAG->getMachineNode(SPU::ILr32, dl, N->getValueType(0), Op1), 0); } } Ops[0] = Op0; n_ops = 2; } } if (n_ops > 0) { if (N->hasOneUse()) return CurDAG->SelectNodeTo(N, NewOpc, OpVT, Ops, n_ops); else return CurDAG->getMachineNode(NewOpc, dl, OpVT, Ops, n_ops); } else return SelectCode(N); }
bool SPUDAGToDAGISel::DFormAddressPredicate(SDNode *Op, SDValue N, SDValue &Base, SDValue &Index, int minOffset, int maxOffset) { unsigned Opc = N.getOpcode(); EVT PtrTy = SPUtli.getPointerTy(); if (Opc == ISD::FrameIndex) { // Stack frame index must be less than 512 (divided by 16): FrameIndexSDNode *FIN = cast<FrameIndexSDNode>(N); int FI = int(FIN->getIndex()); DEBUG(errs() << "SelectDFormAddr: ISD::FrameIndex = " << FI << "\n"); if (SPUFrameLowering::FItoStackOffset(FI) < maxOffset) { Base = CurDAG->getTargetConstant(0, PtrTy); Index = CurDAG->getTargetFrameIndex(FI, PtrTy); return true; } } else if (Opc == ISD::ADD) { // Generated by getelementptr const SDValue Op0 = N.getOperand(0); const SDValue Op1 = N.getOperand(1); if ((Op0.getOpcode() == SPUISD::Hi && Op1.getOpcode() == SPUISD::Lo) || (Op1.getOpcode() == SPUISD::Hi && Op0.getOpcode() == SPUISD::Lo)) { Base = CurDAG->getTargetConstant(0, PtrTy); Index = N; return true; } else if (Op1.getOpcode() == ISD::Constant || Op1.getOpcode() == ISD::TargetConstant) { ConstantSDNode *CN = cast<ConstantSDNode>(Op1); int32_t offset = int32_t(CN->getSExtValue()); if (Op0.getOpcode() == ISD::FrameIndex) { FrameIndexSDNode *FIN = cast<FrameIndexSDNode>(Op0); int FI = int(FIN->getIndex()); DEBUG(errs() << "SelectDFormAddr: ISD::ADD offset = " << offset << " frame index = " << FI << "\n"); if (SPUFrameLowering::FItoStackOffset(FI) < maxOffset) { Base = CurDAG->getTargetConstant(offset, PtrTy); Index = CurDAG->getTargetFrameIndex(FI, PtrTy); return true; } } else if (offset > minOffset && offset < maxOffset) { Base = CurDAG->getTargetConstant(offset, PtrTy); Index = Op0; return true; } } else if (Op0.getOpcode() == ISD::Constant || Op0.getOpcode() == ISD::TargetConstant) { ConstantSDNode *CN = cast<ConstantSDNode>(Op0); int32_t offset = int32_t(CN->getSExtValue()); if (Op1.getOpcode() == ISD::FrameIndex) { FrameIndexSDNode *FIN = cast<FrameIndexSDNode>(Op1); int FI = int(FIN->getIndex()); DEBUG(errs() << "SelectDFormAddr: ISD::ADD offset = " << offset << " frame index = " << FI << "\n"); if (SPUFrameLowering::FItoStackOffset(FI) < maxOffset) { Base = CurDAG->getTargetConstant(offset, PtrTy); Index = CurDAG->getTargetFrameIndex(FI, PtrTy); return true; } } else if (offset > minOffset && offset < maxOffset) { Base = CurDAG->getTargetConstant(offset, PtrTy); Index = Op1; return true; } } } else if (Opc == SPUISD::IndirectAddr) { // Indirect with constant offset -> D-Form address const SDValue Op0 = N.getOperand(0); const SDValue Op1 = N.getOperand(1); if (Op0.getOpcode() == SPUISD::Hi && Op1.getOpcode() == SPUISD::Lo) { // (SPUindirect (SPUhi <arg>, 0), (SPUlo <arg>, 0)) Base = CurDAG->getTargetConstant(0, PtrTy); Index = N; return true; } else if (isa<ConstantSDNode>(Op0) || isa<ConstantSDNode>(Op1)) { int32_t offset = 0; SDValue idxOp; if (isa<ConstantSDNode>(Op1)) { ConstantSDNode *CN = cast<ConstantSDNode>(Op1); offset = int32_t(CN->getSExtValue()); idxOp = Op0; } else if (isa<ConstantSDNode>(Op0)) { ConstantSDNode *CN = cast<ConstantSDNode>(Op0); offset = int32_t(CN->getSExtValue()); idxOp = Op1; } if (offset >= minOffset && offset <= maxOffset) { Base = CurDAG->getTargetConstant(offset, PtrTy); Index = idxOp; return true; } } } else if (Opc == SPUISD::AFormAddr) { Base = CurDAG->getTargetConstant(0, N.getValueType()); Index = N; return true; } else if (Opc == SPUISD::LDRESULT) { Base = CurDAG->getTargetConstant(0, N.getValueType()); Index = N; return true; } else if (Opc == ISD::Register ||Opc == ISD::CopyFromReg ||Opc == ISD::UNDEF ||Opc == ISD::Constant) { unsigned OpOpc = Op->getOpcode(); if (OpOpc == ISD::STORE || OpOpc == ISD::LOAD) { // Direct load/store without getelementptr SDValue Offs; Offs = ((OpOpc == ISD::STORE) ? Op->getOperand(3) : Op->getOperand(2)); if (Offs.getOpcode() == ISD::Constant || Offs.getOpcode() == ISD::UNDEF) { if (Offs.getOpcode() == ISD::UNDEF) Offs = CurDAG->getTargetConstant(0, Offs.getValueType()); Base = Offs; Index = N; return true; } } else { /* If otherwise unadorned, default to D-form address with 0 offset: */ if (Opc == ISD::CopyFromReg) { Index = N.getOperand(1); } else { Index = N; } Base = CurDAG->getTargetConstant(0, Index.getValueType()); return true; } } return false; }
/// ComplexPattern used on MipsInstrInfo /// Used on Mips Load/Store instructions bool MipsDAGToDAGISel:: SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset) { // if Address is FI, get the TargetFrameIndex. if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); Offset = CurDAG->getTargetConstant(0, MVT::i32); return true; } // on PIC code Load GA if (TM.getRelocationModel() == Reloc::PIC_) { if (Addr.getOpcode() == MipsISD::WrapperPIC) { Base = CurDAG->getRegister(Mips::GP, MVT::i32); Offset = Addr.getOperand(0); return true; } } else { if ((Addr.getOpcode() == ISD::TargetExternalSymbol || Addr.getOpcode() == ISD::TargetGlobalAddress)) return false; else if (Addr.getOpcode() == ISD::TargetGlobalTLSAddress) { Base = CurDAG->getRegister(Mips::GP, MVT::i32); Offset = Addr; return true; } } // Addresses of the form FI+const or FI|const if (CurDAG->isBaseWithConstantOffset(Addr)) { ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)); if (isInt<16>(CN->getSExtValue())) { // If the first operand is a FI, get the TargetFI Node if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode> (Addr.getOperand(0))) Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); else Base = Addr.getOperand(0); Offset = CurDAG->getTargetConstant(CN->getZExtValue(), MVT::i32); return true; } } // Operand is a result from an ADD. if (Addr.getOpcode() == ISD::ADD) { // When loading from constant pools, load the lower address part in // the instruction itself. Example, instead of: // lui $2, %hi($CPI1_0) // addiu $2, $2, %lo($CPI1_0) // lwc1 $f0, 0($2) // Generate: // lui $2, %hi($CPI1_0) // lwc1 $f0, %lo($CPI1_0)($2) if ((Addr.getOperand(0).getOpcode() == MipsISD::Hi || Addr.getOperand(0).getOpcode() == ISD::LOAD) && Addr.getOperand(1).getOpcode() == MipsISD::Lo) { SDValue LoVal = Addr.getOperand(1); if (isa<ConstantPoolSDNode>(LoVal.getOperand(0)) || isa<GlobalAddressSDNode>(LoVal.getOperand(0))) { Base = Addr.getOperand(0); Offset = LoVal.getOperand(0); return true; } } } Base = Addr; Offset = CurDAG->getTargetConstant(0, MVT::i32); return true; }
/// ComplexPattern used on MipsInstrInfo /// Used on Mips Load/Store instructions bool MipsDAGToDAGISel:: SelectAddr(SDNode *Parent, SDValue Addr, SDValue &Base, SDValue &Offset) { EVT ValTy = Addr.getValueType(); // If Parent is an unaligned f32 load or store, select a (base + index) // floating point load/store instruction (luxc1 or suxc1). const LSBaseSDNode* LS = 0; if (Parent && (LS = dyn_cast<LSBaseSDNode>(Parent))) { EVT VT = LS->getMemoryVT(); if (VT.getSizeInBits() / 8 > LS->getAlignment()) { assert(TLI.allowsUnalignedMemoryAccesses(VT) && "Unaligned loads/stores not supported for this type."); if (VT == MVT::f32) return false; } } // if Address is FI, get the TargetFrameIndex. if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy); Offset = CurDAG->getTargetConstant(0, ValTy); return true; } // on PIC code Load GA if (Addr.getOpcode() == MipsISD::Wrapper) { Base = Addr.getOperand(0); Offset = Addr.getOperand(1); return true; } if (TM.getRelocationModel() != Reloc::PIC_) { if ((Addr.getOpcode() == ISD::TargetExternalSymbol || Addr.getOpcode() == ISD::TargetGlobalAddress)) return false; } // Addresses of the form FI+const or FI|const if (CurDAG->isBaseWithConstantOffset(Addr)) { ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)); if (isInt<16>(CN->getSExtValue())) { // If the first operand is a FI, get the TargetFI Node if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode> (Addr.getOperand(0))) Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy); else Base = Addr.getOperand(0); Offset = CurDAG->getTargetConstant(CN->getZExtValue(), ValTy); return true; } } // Operand is a result from an ADD. if (Addr.getOpcode() == ISD::ADD) { // When loading from constant pools, load the lower address part in // the instruction itself. Example, instead of: // lui $2, %hi($CPI1_0) // addiu $2, $2, %lo($CPI1_0) // lwc1 $f0, 0($2) // Generate: // lui $2, %hi($CPI1_0) // lwc1 $f0, %lo($CPI1_0)($2) if (Addr.getOperand(1).getOpcode() == MipsISD::Lo) { SDValue LoVal = Addr.getOperand(1); if (isa<ConstantPoolSDNode>(LoVal.getOperand(0)) || isa<GlobalAddressSDNode>(LoVal.getOperand(0))) { Base = Addr.getOperand(0); Offset = LoVal.getOperand(0); return true; } } // If an indexed floating point load/store can be emitted, return false. if (LS && (LS->getMemoryVT() == MVT::f32 || LS->getMemoryVT() == MVT::f64) && Subtarget.hasMips32r2Or64()) return false; } Base = Addr; Offset = CurDAG->getTargetConstant(0, ValTy); return true; }
/// ComplexPattern used on OR1KInstrInfo /// Used on OR1K Load/Store instructions bool OR1KDAGToDAGISel:: SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset) { // if Address is FI, get the TargetFrameIndex. if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); Offset = CurDAG->getTargetConstant(0, MVT::i32); return true; } // on PIC code Load GA if (TM.getRelocationModel() == Reloc::PIC_) { if ((Addr.getOpcode() == ISD::TargetGlobalAddress) || (Addr.getOpcode() == ISD::TargetConstantPool) || (Addr.getOpcode() == ISD::TargetJumpTable)){ OR1KMachineFunctionInfo *MFI = CurDAG->getMachineFunction().getInfo<OR1KMachineFunctionInfo>(); Base = CurDAG->getRegister(MFI->getGlobalBaseReg(), MVT::i32); Offset = Addr; return true; } } else { if ((Addr.getOpcode() == ISD::TargetExternalSymbol || Addr.getOpcode() == ISD::TargetGlobalAddress)) return false; } // Addresses of the form FI+const or FI|const if (CurDAG->isBaseWithConstantOffset(Addr)) { ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)); if (isInt<16>(CN->getSExtValue())) { // If the first operand is a FI, get the TargetFI Node if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode> (Addr.getOperand(0))) Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); else Base = Addr.getOperand(0); Offset = CurDAG->getTargetConstant(CN->getZExtValue(), MVT::i32); return true; } } // Operand is a result from an ADD. if (Addr.getOpcode() == ISD::ADD) { if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) { if (isUInt<16>(CN->getZExtValue())) { // If the first operand is a FI, get the TargetFI Node if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode> (Addr.getOperand(0))) { Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); } else { Base = Addr.getOperand(0); } Offset = CurDAG->getTargetConstant(CN->getZExtValue(), MVT::i32); return true; } } } Base = Addr; Offset = CurDAG->getTargetConstant(0, MVT::i32); return true; }