int ARMTTIImpl::getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy, const Instruction *I) { int ISD = TLI->InstructionOpcodeToISD(Opcode); // On NEON a vector select gets lowered to vbsl. if (ST->hasNEON() && ValTy->isVectorTy() && ISD == ISD::SELECT) { // Lowering of some vector selects is currently far from perfect. static const TypeConversionCostTblEntry NEONVectorSelectTbl[] = { { ISD::SELECT, MVT::v4i1, MVT::v4i64, 4*4 + 1*2 + 1 }, { ISD::SELECT, MVT::v8i1, MVT::v8i64, 50 }, { ISD::SELECT, MVT::v16i1, MVT::v16i64, 100 } }; EVT SelCondTy = TLI->getValueType(DL, CondTy); EVT SelValTy = TLI->getValueType(DL, ValTy); if (SelCondTy.isSimple() && SelValTy.isSimple()) { if (const auto *Entry = ConvertCostTableLookup(NEONVectorSelectTbl, ISD, SelCondTy.getSimpleVT(), SelValTy.getSimpleVT())) return Entry->Cost; } std::pair<int, MVT> LT = TLI->getTypeLegalizationCost(DL, ValTy); return LT.first; } return BaseT::getCmpSelInstrCost(Opcode, ValTy, CondTy, I); }
bool WebAssemblyFastISel::selectBitCast(const Instruction *I) { // Target-independent code can handle this, except it doesn't set the dead // flag on the ARGUMENTS clobber, so we have to do that manually in order // to satisfy code that expects this of isBitcast() instructions. EVT VT = TLI.getValueType(DL, I->getOperand(0)->getType()); EVT RetVT = TLI.getValueType(DL, I->getType()); if (!VT.isSimple() || !RetVT.isSimple()) return false; if (VT == RetVT) { // No-op bitcast. updateValueMap(I, getRegForValue(I->getOperand(0))); return true; } unsigned Reg = fastEmit_ISD_BITCAST_r(VT.getSimpleVT(), RetVT.getSimpleVT(), getRegForValue(I->getOperand(0)), I->getOperand(0)->hasOneUse()); if (!Reg) return false; MachineBasicBlock::iterator Iter = FuncInfo.InsertPt; --Iter; assert(Iter->isBitcast()); Iter->setPhysRegsDeadExcept(ArrayRef<unsigned>(), TRI); updateValueMap(I, Reg); return true; }
unsigned BasicTTI::getMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment, unsigned AddressSpace) const { assert(!Src->isVoidTy() && "Invalid type"); std::pair<unsigned, MVT> LT = getTLI()->getTypeLegalizationCost(Src); // Assuming that all loads of legal types cost 1. unsigned Cost = LT.first; if (Src->isVectorTy() && Src->getPrimitiveSizeInBits() < LT.second.getSizeInBits()) { // This is a vector load that legalizes to a larger type than the vector // itself. Unless the corresponding extending load or truncating store is // legal, then this will scalarize. TargetLowering::LegalizeAction LA = TargetLowering::Expand; EVT MemVT = getTLI()->getValueType(Src, true); if (MemVT.isSimple() && MemVT != MVT::Other) { if (Opcode == Instruction::Store) LA = getTLI()->getTruncStoreAction(LT.second, MemVT.getSimpleVT()); else LA = getTLI()->getLoadExtAction(ISD::EXTLOAD, MemVT.getSimpleVT()); } if (LA != TargetLowering::Legal && LA != TargetLowering::Custom) { // This is a vector load/store for some illegal type that is scalarized. // We must account for the cost of building or decomposing the vector. Cost += getScalarizationOverhead(Src, Opcode != Instruction::Store, Opcode == Instruction::Store); } } return Cost; }
bool FastISel::SelectCast(const User *I, unsigned Opcode) { EVT SrcVT = TLI.getValueType(I->getOperand(0)->getType()); EVT DstVT = TLI.getValueType(I->getType()); if (SrcVT == MVT::Other || !SrcVT.isSimple() || DstVT == MVT::Other || !DstVT.isSimple()) // Unhandled type. Halt "fast" selection and bail. return false; // Check if the destination type is legal. if (!TLI.isTypeLegal(DstVT)) return false; // Check if the source operand is legal. if (!TLI.isTypeLegal(SrcVT)) return false; unsigned InputReg = getRegForValue(I->getOperand(0)); if (!InputReg) // Unhandled operand. Halt "fast" selection and bail. return false; bool InputRegIsKill = hasTrivialKill(I->getOperand(0)); unsigned ResultReg = FastEmit_r(SrcVT.getSimpleVT(), DstVT.getSimpleVT(), Opcode, InputReg, InputRegIsKill); if (!ResultReg) return false; UpdateValueMap(I, ResultReg); return true; }
unsigned ARMTTI::getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy) const { int ISD = TLI->InstructionOpcodeToISD(Opcode); // On NEON a a vector select gets lowered to vbsl. if (ST->hasNEON() && ValTy->isVectorTy() && ISD == ISD::SELECT) { // Lowering of some vector selects is currently far from perfect. static const TypeConversionCostTblEntry<MVT::SimpleValueType> NEONVectorSelectTbl[] = { { ISD::SELECT, MVT::v16i1, MVT::v16i16, 2*16 + 1 + 3*1 + 4*1 }, { ISD::SELECT, MVT::v8i1, MVT::v8i32, 4*8 + 1*3 + 1*4 + 1*2 }, { ISD::SELECT, MVT::v16i1, MVT::v16i32, 4*16 + 1*6 + 1*8 + 1*4 }, { ISD::SELECT, MVT::v4i1, MVT::v4i64, 4*4 + 1*2 + 1 }, { ISD::SELECT, MVT::v8i1, MVT::v8i64, 50 }, { ISD::SELECT, MVT::v16i1, MVT::v16i64, 100 } }; EVT SelCondTy = TLI->getValueType(CondTy); EVT SelValTy = TLI->getValueType(ValTy); if (SelCondTy.isSimple() && SelValTy.isSimple()) { int Idx = ConvertCostTableLookup(NEONVectorSelectTbl, ISD, SelCondTy.getSimpleVT(), SelValTy.getSimpleVT()); if (Idx != -1) return NEONVectorSelectTbl[Idx].Cost; } std::pair<unsigned, MVT> LT = TLI->getTypeLegalizationCost(ValTy); return LT.first; } return TargetTransformInfo::getCmpSelInstrCost(Opcode, ValTy, CondTy); }
int AArch64TTIImpl::getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy) { int ISD = TLI->InstructionOpcodeToISD(Opcode); // We don't lower some vector selects well that are wider than the register // width. if (ValTy->isVectorTy() && ISD == ISD::SELECT) { // We would need this many instructions to hide the scalarization happening. const int AmortizationCost = 20; static const TypeConversionCostTblEntry<MVT::SimpleValueType> VectorSelectTbl[] = { { ISD::SELECT, MVT::v16i1, MVT::v16i16, 16 }, { ISD::SELECT, MVT::v8i1, MVT::v8i32, 8 }, { ISD::SELECT, MVT::v16i1, MVT::v16i32, 16 }, { ISD::SELECT, MVT::v4i1, MVT::v4i64, 4 * AmortizationCost }, { ISD::SELECT, MVT::v8i1, MVT::v8i64, 8 * AmortizationCost }, { ISD::SELECT, MVT::v16i1, MVT::v16i64, 16 * AmortizationCost } }; EVT SelCondTy = TLI->getValueType(DL, CondTy); EVT SelValTy = TLI->getValueType(DL, ValTy); if (SelCondTy.isSimple() && SelValTy.isSimple()) { int Idx = ConvertCostTableLookup(VectorSelectTbl, ISD, SelCondTy.getSimpleVT(), SelValTy.getSimpleVT()); if (Idx != -1) return VectorSelectTbl[Idx].Cost; } } return BaseT::getCmpSelInstrCost(Opcode, ValTy, CondTy); }
bool FastISel::SelectCast(const User *I, unsigned Opcode) { EVT SrcVT = TLI.getValueType(I->getOperand(0)->getType()); EVT DstVT = TLI.getValueType(I->getType()); if (SrcVT == MVT::Other || !SrcVT.isSimple() || DstVT == MVT::Other || !DstVT.isSimple()) // Unhandled type. Halt "fast" selection and bail. return false; // Check if the destination type is legal. Or as a special case, // it may be i1 if we're doing a truncate because that's // easy and somewhat common. if (!TLI.isTypeLegal(DstVT)) if (DstVT != MVT::i1 || Opcode != ISD::TRUNCATE) // Unhandled type. Halt "fast" selection and bail. return false; // Check if the source operand is legal. Or as a special case, // it may be i1 if we're doing zero-extension because that's // easy and somewhat common. if (!TLI.isTypeLegal(SrcVT)) if (SrcVT != MVT::i1 || Opcode != ISD::ZERO_EXTEND) // Unhandled type. Halt "fast" selection and bail. return false; unsigned InputReg = getRegForValue(I->getOperand(0)); if (!InputReg) // Unhandled operand. Halt "fast" selection and bail. return false; bool InputRegIsKill = hasTrivialKill(I->getOperand(0)); // If the operand is i1, arrange for the high bits in the register to be zero. if (SrcVT == MVT::i1) { SrcVT = TLI.getTypeToTransformTo(I->getContext(), SrcVT); InputReg = FastEmitZExtFromI1(SrcVT.getSimpleVT(), InputReg, InputRegIsKill); if (!InputReg) return false; InputRegIsKill = true; } // If the result is i1, truncate to the target's type for i1 first. if (DstVT == MVT::i1) DstVT = TLI.getTypeToTransformTo(I->getContext(), DstVT); unsigned ResultReg = FastEmit_r(SrcVT.getSimpleVT(), DstVT.getSimpleVT(), Opcode, InputReg, InputRegIsKill); if (!ResultReg) return false; UpdateValueMap(I, ResultReg); return true; }
bool FastISel::SelectBitCast(const User *I) { // If the bitcast doesn't change the type, just use the operand value. if (I->getType() == I->getOperand(0)->getType()) { unsigned Reg = getRegForValue(I->getOperand(0)); if (Reg == 0) return false; UpdateValueMap(I, Reg); return true; } // Bitcasts of other values become reg-reg copies or BITCAST operators. EVT SrcVT = TLI.getValueType(I->getOperand(0)->getType()); EVT DstVT = TLI.getValueType(I->getType()); if (SrcVT == MVT::Other || !SrcVT.isSimple() || DstVT == MVT::Other || !DstVT.isSimple() || !TLI.isTypeLegal(SrcVT) || !TLI.isTypeLegal(DstVT)) // Unhandled type. Halt "fast" selection and bail. return false; unsigned Op0 = getRegForValue(I->getOperand(0)); if (Op0 == 0) // Unhandled operand. Halt "fast" selection and bail. return false; bool Op0IsKill = hasTrivialKill(I->getOperand(0)); // First, try to perform the bitcast by inserting a reg-reg copy. unsigned ResultReg = 0; if (SrcVT.getSimpleVT() == DstVT.getSimpleVT()) { TargetRegisterClass* SrcClass = TLI.getRegClassFor(SrcVT); TargetRegisterClass* DstClass = TLI.getRegClassFor(DstVT); // Don't attempt a cross-class copy. It will likely fail. if (SrcClass == DstClass) { ResultReg = createResultReg(DstClass); BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(TargetOpcode::COPY), ResultReg).addReg(Op0); } } // If the reg-reg copy failed, select a BITCAST opcode. if (!ResultReg) ResultReg = FastEmit_r(SrcVT.getSimpleVT(), DstVT.getSimpleVT(), ISD::BITCAST, Op0, Op0IsKill); if (!ResultReg) return false; UpdateValueMap(I, ResultReg); return true; }
bool FastISel::SelectBitCast(User *I) { // If the bitcast doesn't change the type, just use the operand value. if (I->getType() == I->getOperand(0)->getType()) { unsigned Reg = getRegForValue(I->getOperand(0)); if (Reg == 0) return false; UpdateValueMap(I, Reg); return true; } // Bitcasts of other values become reg-reg copies or BIT_CONVERT operators. EVT SrcVT = TLI.getValueType(I->getOperand(0)->getType()); EVT DstVT = TLI.getValueType(I->getType()); if (SrcVT == MVT::Other || !SrcVT.isSimple() || DstVT == MVT::Other || !DstVT.isSimple() || !TLI.isTypeLegal(SrcVT) || !TLI.isTypeLegal(DstVT)) // Unhandled type. Halt "fast" selection and bail. return false; unsigned Op0 = getRegForValue(I->getOperand(0)); if (Op0 == 0) // Unhandled operand. Halt "fast" selection and bail. return false; // First, try to perform the bitcast by inserting a reg-reg copy. unsigned ResultReg = 0; if (SrcVT.getSimpleVT() == DstVT.getSimpleVT()) { TargetRegisterClass* SrcClass = TLI.getRegClassFor(SrcVT); TargetRegisterClass* DstClass = TLI.getRegClassFor(DstVT); ResultReg = createResultReg(DstClass); bool InsertedCopy = TII.copyRegToReg(*MBB, MBB->end(), ResultReg, Op0, DstClass, SrcClass); if (!InsertedCopy) ResultReg = 0; } // If the reg-reg copy failed, select a BIT_CONVERT opcode. if (!ResultReg) ResultReg = FastEmit_r(SrcVT.getSimpleVT(), DstVT.getSimpleVT(), ISD::BIT_CONVERT, Op0); if (!ResultReg) return false; UpdateValueMap(I, ResultReg); return true; }
// HandleByVal - Allocate a stack slot large enough to pass an argument by // value. The size and alignment information of the argument is encoded in its // parameter attribute. void Hexagon_CCState::HandleByVal(unsigned ValNo, EVT ValVT, EVT LocVT, CCValAssign::LocInfo LocInfo, int MinSize, int MinAlign, ISD::ArgFlagsTy ArgFlags) { unsigned Align = ArgFlags.getByValAlign(); unsigned Size = ArgFlags.getByValSize(); if (MinSize > (int)Size) Size = MinSize; if (MinAlign > (int)Align) Align = MinAlign; unsigned Offset = AllocateStack(Size, Align); addLoc(CCValAssign::getMem(ValNo, ValVT.getSimpleVT(), Offset, LocVT.getSimpleVT(), LocInfo)); }
unsigned FastISel::getRegForGEPIndex(Value *Idx) { unsigned IdxN = getRegForValue(Idx); if (IdxN == 0) // Unhandled operand. Halt "fast" selection and bail. return 0; // If the index is smaller or larger than intptr_t, truncate or extend it. MVT PtrVT = TLI.getPointerTy(); EVT IdxVT = EVT::getEVT(Idx->getType(), /*HandleUnknown=*/false); if (IdxVT.bitsLT(PtrVT)) IdxN = FastEmit_r(IdxVT.getSimpleVT(), PtrVT, ISD::SIGN_EXTEND, IdxN); else if (IdxVT.bitsGT(PtrVT)) IdxN = FastEmit_r(IdxVT.getSimpleVT(), PtrVT, ISD::TRUNCATE, IdxN); return IdxN; }
SDNode *PTXDAGToDAGISel::SelectREADPARAM(SDNode *Node) { SDValue Chain = Node->getOperand(0); SDValue Index = Node->getOperand(1); int OpCode; // Get the type of parameter we are reading EVT VT = Node->getValueType(0); assert(VT.isSimple() && "READ_PARAM only implemented for MVT types"); MVT Type = VT.getSimpleVT(); if (Type == MVT::i1) OpCode = PTX::READPARAMPRED; else if (Type == MVT::i16) OpCode = PTX::READPARAMI16; else if (Type == MVT::i32) OpCode = PTX::READPARAMI32; else if (Type == MVT::i64) OpCode = PTX::READPARAMI64; else if (Type == MVT::f32) OpCode = PTX::READPARAMF32; else { assert(Type == MVT::f64 && "Unexpected type!"); OpCode = PTX::READPARAMF64; } SDValue Pred = CurDAG->getRegister(PTX::NoRegister, MVT::i1); SDValue PredOp = CurDAG->getTargetConstant(PTXPredicate::None, MVT::i32); DebugLoc dl = Node->getDebugLoc(); SDValue Ops[] = { Index, Pred, PredOp, Chain }; return CurDAG->getMachineNode(OpCode, dl, VT, Ops, 4); }
bool ARMFastISel::ARMEmitStore(EVT VT, unsigned SrcReg, unsigned DstReg, int Offset) { unsigned StrOpc; switch (VT.getSimpleVT().SimpleTy) { default: return false; case MVT::i1: case MVT::i8: StrOpc = isThumb ? ARM::tSTRB : ARM::STRB; break; case MVT::i16: StrOpc = isThumb ? ARM::tSTRH : ARM::STRH; break; case MVT::i32: StrOpc = isThumb ? ARM::tSTR : ARM::STR; break; case MVT::f32: if (!Subtarget->hasVFP2()) return false; StrOpc = ARM::VSTRS; break; case MVT::f64: if (!Subtarget->hasVFP2()) return false; StrOpc = ARM::VSTRD; break; } if (isThumb) AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(StrOpc), SrcReg) .addReg(DstReg).addImm(Offset).addReg(0)); else AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(StrOpc), SrcReg) .addReg(DstReg).addReg(0).addImm(Offset)); return true; }
unsigned AArch64TTI::getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) const { int ISD = TLI->InstructionOpcodeToISD(Opcode); assert(ISD && "Invalid opcode"); EVT SrcTy = TLI->getValueType(Src); EVT DstTy = TLI->getValueType(Dst); if (!SrcTy.isSimple() || !DstTy.isSimple()) return TargetTransformInfo::getCastInstrCost(Opcode, Dst, Src); static const TypeConversionCostTblEntry<MVT> ConversionTbl[] = { // LowerVectorINT_TO_FP: { ISD::SINT_TO_FP, MVT::v2f32, MVT::v2i32, 1 }, { ISD::SINT_TO_FP, MVT::v2f64, MVT::v2i8, 1 }, { ISD::SINT_TO_FP, MVT::v2f64, MVT::v2i16, 1 }, { ISD::SINT_TO_FP, MVT::v2f64, MVT::v2i32, 1 }, { ISD::SINT_TO_FP, MVT::v2f64, MVT::v2i64, 1 }, { ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i32, 1 }, { ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i8, 1 }, { ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i16, 1 }, { ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i32, 1 }, { ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i64, 1 }, // LowerVectorFP_TO_INT { ISD::FP_TO_SINT, MVT::v4i32, MVT::v4f32, 1 }, { ISD::FP_TO_SINT, MVT::v2i64, MVT::v2f64, 1 }, { ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f32, 1 }, { ISD::FP_TO_UINT, MVT::v2i64, MVT::v2f64, 1 }, { ISD::FP_TO_UINT, MVT::v2i32, MVT::v2f64, 1 }, { ISD::FP_TO_SINT, MVT::v2i32, MVT::v2f64, 1 }, { ISD::FP_TO_UINT, MVT::v2i64, MVT::v2f32, 4 }, { ISD::FP_TO_SINT, MVT::v2i64, MVT::v2f32, 4 }, { ISD::FP_TO_UINT, MVT::v4i16, MVT::v4f32, 4 }, { ISD::FP_TO_SINT, MVT::v4i16, MVT::v4f32, 4 }, { ISD::FP_TO_UINT, MVT::v2i64, MVT::v2f64, 4 }, { ISD::FP_TO_SINT, MVT::v2i64, MVT::v2f64, 4 }, }; int Idx = ConvertCostTableLookup<MVT>( ConversionTbl, array_lengthof(ConversionTbl), ISD, DstTy.getSimpleVT(), SrcTy.getSimpleVT()); if (Idx != -1) return ConversionTbl[Idx].Cost; return TargetTransformInfo::getCastInstrCost(Opcode, Dst, Src); }
/// FastEmit_rf_ - This method is a wrapper of FastEmit_ri. It first tries /// to emit an instruction with a floating-point immediate operand using /// FastEmit_rf. If that fails, it materializes the immediate into a register /// and try FastEmit_rr instead. unsigned FastISel::FastEmit_rf_(MVT VT, unsigned Opcode, unsigned Op0, bool Op0IsKill, const ConstantFP *FPImm, MVT ImmType) { // First check if immediate type is legal. If not, we can't use the rf form. unsigned ResultReg = FastEmit_rf(VT, VT, Opcode, Op0, Op0IsKill, FPImm); if (ResultReg != 0) return ResultReg; // Materialize the constant in a register. unsigned MaterialReg = FastEmit_f(ImmType, ImmType, ISD::ConstantFP, FPImm); if (MaterialReg == 0) { // If the target doesn't have a way to directly enter a floating-point // value into a register, use an alternate approach. // TODO: The current approach only supports floating-point constants // that can be constructed by conversion from integer values. This should // be replaced by code that creates a load from a constant-pool entry, // which will require some target-specific work. const APFloat &Flt = FPImm->getValueAPF(); EVT IntVT = TLI.getPointerTy(); uint64_t x[2]; uint32_t IntBitWidth = IntVT.getSizeInBits(); bool isExact; (void) Flt.convertToInteger(x, IntBitWidth, /*isSigned=*/true, APFloat::rmTowardZero, &isExact); if (!isExact) return 0; APInt IntVal(IntBitWidth, 2, x); unsigned IntegerReg = FastEmit_i(IntVT.getSimpleVT(), IntVT.getSimpleVT(), ISD::Constant, IntVal.getZExtValue()); if (IntegerReg == 0) return 0; MaterialReg = FastEmit_r(IntVT.getSimpleVT(), VT, ISD::SINT_TO_FP, IntegerReg, /*Kill=*/true); if (MaterialReg == 0) return 0; } return FastEmit_rr(VT, VT, Opcode, Op0, Op0IsKill, MaterialReg, /*Kill=*/true); }
bool MipsFastISel::isTypeLegal(Type *Ty, MVT &VT) { EVT evt = TLI.getValueType(Ty, true); // Only handle simple types. if (evt == MVT::Other || !evt.isSimple()) return false; VT = evt.getSimpleVT(); // Handle all legal types, i.e. a register that will directly hold this // value. return TLI.isTypeLegal(VT); }
unsigned X86TTI::getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) const { int ISD = TLI->InstructionOpcodeToISD(Opcode); assert(ISD && "Invalid opcode"); EVT SrcTy = TLI->getValueType(Src); EVT DstTy = TLI->getValueType(Dst); if (!SrcTy.isSimple() || !DstTy.isSimple()) return TargetTransformInfo::getCastInstrCost(Opcode, Dst, Src); static const TypeConversionCostTblEntry<MVT> AVXConversionTbl[] = { { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i16, 1 }, { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i16, 1 }, { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i32, 1 }, { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i32, 1 }, { ISD::TRUNCATE, MVT::v4i32, MVT::v4i64, 1 }, { ISD::TRUNCATE, MVT::v8i16, MVT::v8i32, 1 }, { ISD::SINT_TO_FP, MVT::v8f32, MVT::v8i8, 1 }, { ISD::SINT_TO_FP, MVT::v4f32, MVT::v4i8, 1 }, { ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i8, 1 }, { ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i8, 1 }, { ISD::FP_TO_SINT, MVT::v8i8, MVT::v8f32, 1 }, { ISD::FP_TO_SINT, MVT::v4i8, MVT::v4f32, 1 }, { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i1, 6 }, { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i1, 9 }, { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i1, 8 }, { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i8, 6 }, { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i16, 6 }, { ISD::TRUNCATE, MVT::v8i32, MVT::v8i64, 3 }, }; if (ST->hasAVX()) { int Idx = ConvertCostTableLookup<MVT>(AVXConversionTbl, array_lengthof(AVXConversionTbl), ISD, DstTy.getSimpleVT(), SrcTy.getSimpleVT()); if (Idx != -1) return AVXConversionTbl[Idx].Cost; } return TargetTransformInfo::getCastInstrCost(Opcode, Dst, Src); }
bool Cpu0TargetLowering::allowsUnalignedMemoryAccesses(EVT VT) const { MVT::SimpleValueType SVT = VT.getSimpleVT().SimpleTy; switch (SVT) { case MVT::i64: case MVT::i32: case MVT::i16: return true; default: return false; } }
bool MipsSETargetLowering::allowsUnalignedMemoryAccesses(EVT VT, bool *Fast) const { MVT::SimpleValueType SVT = VT.getSimpleVT().SimpleTy; switch (SVT) { case MVT::i64: case MVT::i32: if (Fast) *Fast = true; return true; default: return false; } }
std::pair<unsigned, bool> FastISel::getRegForGEPIndex(const Value *Idx) { unsigned IdxN = getRegForValue(Idx); if (IdxN == 0) // Unhandled operand. Halt "fast" selection and bail. return std::pair<unsigned, bool>(0, false); bool IdxNIsKill = hasTrivialKill(Idx); // If the index is smaller or larger than intptr_t, truncate or extend it. MVT PtrVT = TLI.getPointerTy(); EVT IdxVT = EVT::getEVT(Idx->getType(), /*HandleUnknown=*/false); if (IdxVT.bitsLT(PtrVT)) { IdxN = FastEmit_r(IdxVT.getSimpleVT(), PtrVT, ISD::SIGN_EXTEND, IdxN, IdxNIsKill); IdxNIsKill = true; } else if (IdxVT.bitsGT(PtrVT)) { IdxN = FastEmit_r(IdxVT.getSimpleVT(), PtrVT, ISD::TRUNCATE, IdxN, IdxNIsKill); IdxNIsKill = true; } return std::pair<unsigned, bool>(IdxN, IdxNIsKill); }
unsigned FastISel::getRegForValue(const Value *V) { EVT RealVT = TLI.getValueType(V->getType(), /*AllowUnknown=*/true); // Don't handle non-simple values in FastISel. if (!RealVT.isSimple()) return 0; // Ignore illegal types. We must do this before looking up the value // in ValueMap because Arguments are given virtual registers regardless // of whether FastISel can handle them. MVT VT = RealVT.getSimpleVT(); if (!TLI.isTypeLegal(VT)) { // Promote MVT::i1 to a legal type though, because it's common and easy. if (VT == MVT::i1) VT = TLI.getTypeToTransformTo(V->getContext(), VT).getSimpleVT(); else return 0; } // Look up the value to see if we already have a register for it. We // cache values defined by Instructions across blocks, and other values // only locally. This is because Instructions already have the SSA // def-dominates-use requirement enforced. DenseMap<const Value *, unsigned>::iterator I = FuncInfo.ValueMap.find(V); if (I != FuncInfo.ValueMap.end()) { unsigned Reg = I->second; return Reg; } unsigned Reg = LocalValueMap[V]; if (Reg != 0) return Reg; // In bottom-up mode, just create the virtual register which will be used // to hold the value. It will be materialized later. if (isa<Instruction>(V) && (!isa<AllocaInst>(V) || !FuncInfo.StaticAllocaMap.count(cast<AllocaInst>(V)))) return FuncInfo.InitializeRegForValue(V); SavePoint SaveInsertPt = enterLocalValueArea(); // Materialize the value in a register. Emit any instructions in the // local value area. Reg = materializeRegForValue(V, VT); leaveLocalValueArea(SaveInsertPt); return Reg; }
SDValue PTXTargetLowering:: LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const { EVT PtrVT = getPointerTy(); DebugLoc dl = Op.getDebugLoc(); const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal(); assert(PtrVT.isSimple() && "Pointer must be to primitive type."); SDValue targetGlobal = DAG.getTargetGlobalAddress(GV, dl, PtrVT); SDValue movInstr = DAG.getNode(PTXISD::COPY_ADDRESS, dl, PtrVT.getSimpleVT(), targetGlobal); return movInstr; }
// Materialize a constant into a register, and return the register // number (or zero if we failed to handle it). unsigned MipsFastISel::fastMaterializeConstant(const Constant *C) { EVT CEVT = TLI.getValueType(C->getType(), true); // Only handle simple types. if (!CEVT.isSimple()) return 0; MVT VT = CEVT.getSimpleVT(); if (const ConstantFP *CFP = dyn_cast<ConstantFP>(C)) return (UnsupportedFPMode) ? 0 : materializeFP(CFP, VT); else if (const GlobalValue *GV = dyn_cast<GlobalValue>(C)) return materializeGV(GV, VT); else if (isa<ConstantInt>(C)) return materializeInt(C, VT); return 0; }
/// SelectFNeg - Emit an FNeg operation. /// bool FastISel::SelectFNeg(const User *I) { unsigned OpReg = getRegForValue(BinaryOperator::getFNegArgument(I)); if (OpReg == 0) return false; bool OpRegIsKill = hasTrivialKill(I); // If the target has ISD::FNEG, use it. EVT VT = TLI.getValueType(I->getType()); unsigned ResultReg = FastEmit_r(VT.getSimpleVT(), VT.getSimpleVT(), ISD::FNEG, OpReg, OpRegIsKill); if (ResultReg != 0) { UpdateValueMap(I, ResultReg); return true; } // Bitcast the value to integer, twiddle the sign bit with xor, // and then bitcast it back to floating-point. if (VT.getSizeInBits() > 64) return false; EVT IntVT = EVT::getIntegerVT(I->getContext(), VT.getSizeInBits()); if (!TLI.isTypeLegal(IntVT)) return false; unsigned IntReg = FastEmit_r(VT.getSimpleVT(), IntVT.getSimpleVT(), ISD::BITCAST, OpReg, OpRegIsKill); if (IntReg == 0) return false; unsigned IntResultReg = FastEmit_ri_(IntVT.getSimpleVT(), ISD::XOR, IntReg, /*Kill=*/true, UINT64_C(1) << (VT.getSizeInBits()-1), IntVT.getSimpleVT()); if (IntResultReg == 0) return false; ResultReg = FastEmit_r(IntVT.getSimpleVT(), VT.getSimpleVT(), ISD::BITCAST, IntResultReg, /*Kill=*/true); if (ResultReg == 0) return false; UpdateValueMap(I, ResultReg); return true; }
SDNode *PTXDAGToDAGISel::SelectWRITEPARAM(SDNode *Node) { SDValue Chain = Node->getOperand(0); SDValue Value = Node->getOperand(1); int OpCode; //Node->dumpr(CurDAG); // Get the type of parameter we are writing EVT VT = Value->getValueType(0); assert(VT.isSimple() && "WRITE_PARAM only implemented for MVT types"); MVT Type = VT.getSimpleVT(); if (Type == MVT::i1) OpCode = PTX::WRITEPARAMPRED; else if (Type == MVT::i16) OpCode = PTX::WRITEPARAMI16; else if (Type == MVT::i32) OpCode = PTX::WRITEPARAMI32; else if (Type == MVT::i64) OpCode = PTX::WRITEPARAMI64; else if (Type == MVT::f32) OpCode = PTX::WRITEPARAMF32; else if (Type == MVT::f64) OpCode = PTX::WRITEPARAMF64; else llvm_unreachable("Invalid type in SelectWRITEPARAM"); SDValue Pred = CurDAG->getRegister(PTX::NoRegister, MVT::i1); SDValue PredOp = CurDAG->getTargetConstant(PTXPredicate::None, MVT::i32); DebugLoc dl = Node->getDebugLoc(); SDValue Ops[] = { Value, Pred, PredOp, Chain }; SDNode* Ret = CurDAG->getMachineNode(OpCode, dl, MVT::Other, Ops, 4); //dbgs() << "SelectWRITEPARAM produced:\n\t"; //Ret->dumpr(CurDAG); return Ret; }
unsigned FastISel::getRegForValue(const Value *V) { EVT RealVT = TLI.getValueType(V->getType(), /*AllowUnknown=*/true); // Don't handle non-simple values in FastISel. if (!RealVT.isSimple()) return 0; // Ignore illegal types. We must do this before looking up the value // in ValueMap because Arguments are given virtual registers regardless // of whether FastISel can handle them. MVT VT = RealVT.getSimpleVT(); if (!TLI.isTypeLegal(VT)) { // Handle integer promotions, though, because they're common and easy. if (VT == MVT::i1 || VT == MVT::i8 || VT == MVT::i16) VT = TLI.getTypeToTransformTo(V->getContext(), VT).getSimpleVT(); else return 0; } // Look up the value to see if we already have a register for it. unsigned Reg = lookUpRegForValue(V); if (Reg != 0) return Reg; // In bottom-up mode, just create the virtual register which will be used // to hold the value. It will be materialized later. if (isa<Instruction>(V) && (!isa<AllocaInst>(V) || !FuncInfo.StaticAllocaMap.count(cast<AllocaInst>(V)))) return FuncInfo.InitializeRegForValue(V); SavePoint SaveInsertPt = enterLocalValueArea(); // Materialize the value in a register. Emit any instructions in the // local value area. Reg = materializeRegForValue(V, VT); leaveLocalValueArea(SaveInsertPt); return Reg; }
bool FastISel::SelectExtractValue(const User *U) { const ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(U); if (!EVI) return false; // Make sure we only try to handle extracts with a legal result. But also // allow i1 because it's easy. EVT RealVT = TLI.getValueType(EVI->getType(), /*AllowUnknown=*/true); if (!RealVT.isSimple()) return false; MVT VT = RealVT.getSimpleVT(); if (!TLI.isTypeLegal(VT) && VT != MVT::i1) return false; const Value *Op0 = EVI->getOperand(0); const Type *AggTy = Op0->getType(); // Get the base result register. unsigned ResultReg; DenseMap<const Value *, unsigned>::iterator I = FuncInfo.ValueMap.find(Op0); if (I != FuncInfo.ValueMap.end()) ResultReg = I->second; else if (isa<Instruction>(Op0)) ResultReg = FuncInfo.InitializeRegForValue(Op0); else return false; // fast-isel can't handle aggregate constants at the moment // Get the actual result register, which is an offset from the base register. unsigned VTIndex = ComputeLinearIndex(AggTy, EVI->idx_begin(), EVI->idx_end()); SmallVector<EVT, 4> AggValueVTs; ComputeValueVTs(TLI, AggTy, AggValueVTs); for (unsigned i = 0; i < VTIndex; i++) ResultReg += TLI.getNumRegisters(FuncInfo.Fn->getContext(), AggValueVTs[i]); UpdateValueMap(EVI, ResultReg); return true; }
std::pair<unsigned, MVT> TargetLoweringBase::getTypeLegalizationCost(Type *Ty) const { LLVMContext &C = Ty->getContext(); EVT MTy = getValueType(Ty); unsigned Cost = 1; // We keep legalizing the type until we find a legal kind. We assume that // the only operation that costs anything is the split. After splitting // we need to handle two types. while (true) { LegalizeKind LK = getTypeConversion(C, MTy); if (LK.first == TypeLegal) return std::make_pair(Cost, MTy.getSimpleVT()); if (LK.first == TypeSplitVector || LK.first == TypeExpandInteger) Cost *= 2; // Keep legalizing the type. MTy = LK.second; } }
bool ARMFastISel::ARMEmitLoad(EVT VT, unsigned &ResultReg, unsigned Reg, int Offset) { assert(VT.isSimple() && "Non-simple types are invalid here!"); unsigned Opc; switch (VT.getSimpleVT().SimpleTy) { default: assert(false && "Trying to emit for an unhandled type!"); return false; case MVT::i16: Opc = isThumb ? ARM::tLDRH : ARM::LDRH; VT = MVT::i32; break; case MVT::i8: Opc = isThumb ? ARM::tLDRB : ARM::LDRB; VT = MVT::i32; break; case MVT::i32: Opc = isThumb ? ARM::tLDR : ARM::LDR; break; } ResultReg = createResultReg(TLI.getRegClassFor(VT)); // TODO: Fix the Addressing modes so that these can share some code. // Since this is a Thumb1 load this will work in Thumb1 or 2 mode. if (isThumb) AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(Opc), ResultReg) .addReg(Reg).addImm(Offset).addReg(0)); else AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(Opc), ResultReg) .addReg(Reg).addReg(0).addImm(Offset)); return true; }
/// LowerCCCArguments - transform physical registers into virtual registers and /// generate load operations for arguments places on the stack. // FIXME: struct return stuff // FIXME: varargs SDValue MSP430TargetLowering::LowerCCCArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl<ISD::InputArg> &Ins, DebugLoc dl, SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo *MFI = MF.getFrameInfo(); MachineRegisterInfo &RegInfo = MF.getRegInfo(); // Assign locations to all of the incoming arguments. SmallVector<CCValAssign, 16> ArgLocs; CCState CCInfo(CallConv, isVarArg, getTargetMachine(), ArgLocs, *DAG.getContext()); CCInfo.AnalyzeFormalArguments(Ins, CC_MSP430); assert(!isVarArg && "Varargs not supported yet"); for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { CCValAssign &VA = ArgLocs[i]; if (VA.isRegLoc()) { // Arguments passed in registers EVT RegVT = VA.getLocVT(); switch (RegVT.getSimpleVT().SimpleTy) { default: { #ifndef NDEBUG errs() << "LowerFormalArguments Unhandled argument type: " << RegVT.getSimpleVT().SimpleTy << "\n"; #endif llvm_unreachable(0); } case MVT::i16: unsigned VReg = RegInfo.createVirtualRegister(MSP430::GR16RegisterClass); RegInfo.addLiveIn(VA.getLocReg(), VReg); SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, VReg, RegVT); // If this is an 8-bit value, it is really passed promoted to 16 // bits. Insert an assert[sz]ext to capture this, then truncate to the // right size. if (VA.getLocInfo() == CCValAssign::SExt) ArgValue = DAG.getNode(ISD::AssertSext, dl, RegVT, ArgValue, DAG.getValueType(VA.getValVT())); else if (VA.getLocInfo() == CCValAssign::ZExt) ArgValue = DAG.getNode(ISD::AssertZext, dl, RegVT, ArgValue, DAG.getValueType(VA.getValVT())); if (VA.getLocInfo() != CCValAssign::Full) ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue); InVals.push_back(ArgValue); } } else { // Sanity check assert(VA.isMemLoc()); // Load the argument to a virtual register unsigned ObjSize = VA.getLocVT().getSizeInBits()/8; if (ObjSize > 2) { errs() << "LowerFormalArguments Unhandled argument type: " << EVT(VA.getLocVT()).getEVTString() << "\n"; } // Create the frame index object for this incoming parameter... int FI = MFI->CreateFixedObject(ObjSize, VA.getLocMemOffset(), true); // Create the SelectionDAG nodes corresponding to a load //from this parameter SDValue FIN = DAG.getFrameIndex(FI, MVT::i16); InVals.push_back(DAG.getLoad(VA.getLocVT(), dl, Chain, FIN, MachinePointerInfo::getFixedStack(FI), false, false, 0)); } } return Chain; }