diff options
Diffstat (limited to 'llvm/lib/Target/ARM/ARMISelLowering.cpp')
| -rw-r--r-- | llvm/lib/Target/ARM/ARMISelLowering.cpp | 168 |
1 files changed, 13 insertions, 155 deletions
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp index 1733424a8b66..a35582bebb08 100644 --- a/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -19283,149 +19283,6 @@ bool ARMTargetLowering::isFNegFree(EVT VT) const { return false; } -/// Check if Ext1 and Ext2 are extends of the same type, doubling the bitwidth -/// of the vector elements. -static bool areExtractExts(Value *Ext1, Value *Ext2) { - auto areExtDoubled = [](Instruction *Ext) { - return Ext->getType()->getScalarSizeInBits() == - 2 * Ext->getOperand(0)->getType()->getScalarSizeInBits(); - }; - - if (!match(Ext1, m_ZExtOrSExt(m_Value())) || - !match(Ext2, m_ZExtOrSExt(m_Value())) || - !areExtDoubled(cast<Instruction>(Ext1)) || - !areExtDoubled(cast<Instruction>(Ext2))) - return false; - - return true; -} - -/// Check if sinking \p I's operands to I's basic block is profitable, because -/// the operands can be folded into a target instruction, e.g. -/// sext/zext can be folded into vsubl. -bool ARMTargetLowering::shouldSinkOperands(Instruction *I, - SmallVectorImpl<Use *> &Ops) const { - if (!I->getType()->isVectorTy()) - return false; - - if (Subtarget->hasNEON()) { - switch (I->getOpcode()) { - case Instruction::Sub: - case Instruction::Add: { - if (!areExtractExts(I->getOperand(0), I->getOperand(1))) - return false; - Ops.push_back(&I->getOperandUse(0)); - Ops.push_back(&I->getOperandUse(1)); - return true; - } - default: - return false; - } - } - - if (!Subtarget->hasMVEIntegerOps()) - return false; - - auto IsFMSMul = [&](Instruction *I) { - if (!I->hasOneUse()) - return false; - auto *Sub = cast<Instruction>(*I->users().begin()); - return Sub->getOpcode() == Instruction::FSub && Sub->getOperand(1) == I; - }; - auto IsFMS = [&](Instruction *I) { - if (match(I->getOperand(0), m_FNeg(m_Value())) || - match(I->getOperand(1), m_FNeg(m_Value()))) - return true; - return false; - }; - - auto IsSinker = [&](Instruction *I, int Operand) { - switch (I->getOpcode()) { - case Instruction::Add: - case Instruction::Mul: - case Instruction::FAdd: - case Instruction::ICmp: - case Instruction::FCmp: - return true; - case Instruction::FMul: - return !IsFMSMul(I); - case Instruction::Sub: - case Instruction::FSub: - case Instruction::Shl: - case Instruction::LShr: - case Instruction::AShr: - return Operand == 1; - case Instruction::Call: - if (auto *II = dyn_cast<IntrinsicInst>(I)) { - switch (II->getIntrinsicID()) { - case Intrinsic::fma: - return !IsFMS(I); - case Intrinsic::sadd_sat: - case Intrinsic::uadd_sat: - case Intrinsic::arm_mve_add_predicated: - case Intrinsic::arm_mve_mul_predicated: - case Intrinsic::arm_mve_qadd_predicated: - case Intrinsic::arm_mve_vhadd: - case Intrinsic::arm_mve_hadd_predicated: - case Intrinsic::arm_mve_vqdmull: - case Intrinsic::arm_mve_vqdmull_predicated: - case Intrinsic::arm_mve_vqdmulh: - case Intrinsic::arm_mve_qdmulh_predicated: - case Intrinsic::arm_mve_vqrdmulh: - case Intrinsic::arm_mve_qrdmulh_predicated: - case Intrinsic::arm_mve_fma_predicated: - return true; - case Intrinsic::ssub_sat: - case Intrinsic::usub_sat: - case Intrinsic::arm_mve_sub_predicated: - case Intrinsic::arm_mve_qsub_predicated: - case Intrinsic::arm_mve_hsub_predicated: - case Intrinsic::arm_mve_vhsub: - return Operand == 1; - default: - return false; - } - } - return false; - default: - return false; - } - }; - - for (auto OpIdx : enumerate(I->operands())) { - Instruction *Op = dyn_cast<Instruction>(OpIdx.value().get()); - // Make sure we are not already sinking this operand - if (!Op || any_of(Ops, [&](Use *U) { return U->get() == Op; })) - continue; - - Instruction *Shuffle = Op; - if (Shuffle->getOpcode() == Instruction::BitCast) - Shuffle = dyn_cast<Instruction>(Shuffle->getOperand(0)); - // We are looking for a splat that can be sunk. - if (!Shuffle || - !match(Shuffle, m_Shuffle( - m_InsertElt(m_Undef(), m_Value(), m_ZeroInt()), - m_Undef(), m_ZeroMask()))) - continue; - if (!IsSinker(I, OpIdx.index())) - continue; - - // All uses of the shuffle should be sunk to avoid duplicating it across gpr - // and vector registers - for (Use &U : Op->uses()) { - Instruction *Insn = cast<Instruction>(U.getUser()); - if (!IsSinker(Insn, U.getOperandNo())) - return false; - } - - Ops.push_back(&Shuffle->getOperandUse(0)); - if (Shuffle != Op) - Ops.push_back(&Op->getOperandUse(0)); - Ops.push_back(&OpIdx.value()); - } - return true; -} - Type *ARMTargetLowering::shouldConvertSplatType(ShuffleVectorInst *SVI) const { if (!Subtarget->hasMVEIntegerOps()) return nullptr; @@ -21292,7 +21149,7 @@ Instruction *ARMTargetLowering::makeDMB(IRBuilderBase &Builder, // Thumb1 and pre-v6 ARM mode use a libcall instead and should never get // here. if (Subtarget->hasV6Ops() && !Subtarget->isThumb()) { - Function *MCR = Intrinsic::getDeclaration(M, Intrinsic::arm_mcr); + Function *MCR = Intrinsic::getOrInsertDeclaration(M, Intrinsic::arm_mcr); Value* args[6] = {Builder.getInt32(15), Builder.getInt32(0), Builder.getInt32(0), Builder.getInt32(7), Builder.getInt32(10), Builder.getInt32(5)}; @@ -21303,7 +21160,7 @@ Instruction *ARMTargetLowering::makeDMB(IRBuilderBase &Builder, llvm_unreachable("makeDMB on a target so old that it has no barriers"); } } else { - Function *DMB = Intrinsic::getDeclaration(M, Intrinsic::arm_dmb); + Function *DMB = Intrinsic::getOrInsertDeclaration(M, Intrinsic::arm_dmb); // Only a full system barrier exists in the M-class architectures. Domain = Subtarget->isMClass() ? ARM_MB::SY : Domain; Constant *CDomain = Builder.getInt32(Domain); @@ -21560,7 +21417,7 @@ Value *ARMTargetLowering::emitLoadLinked(IRBuilderBase &Builder, Type *ValueTy, if (ValueTy->getPrimitiveSizeInBits() == 64) { Intrinsic::ID Int = IsAcquire ? Intrinsic::arm_ldaexd : Intrinsic::arm_ldrexd; - Function *Ldrex = Intrinsic::getDeclaration(M, Int); + Function *Ldrex = Intrinsic::getOrInsertDeclaration(M, Int); Value *LoHi = Builder.CreateCall(Ldrex, Addr, "lohi"); @@ -21576,7 +21433,7 @@ Value *ARMTargetLowering::emitLoadLinked(IRBuilderBase &Builder, Type *ValueTy, Type *Tys[] = { Addr->getType() }; Intrinsic::ID Int = IsAcquire ? Intrinsic::arm_ldaex : Intrinsic::arm_ldrex; - Function *Ldrex = Intrinsic::getDeclaration(M, Int, Tys); + Function *Ldrex = Intrinsic::getOrInsertDeclaration(M, Int, Tys); CallInst *CI = Builder.CreateCall(Ldrex, Addr); CI->addParamAttr( @@ -21589,7 +21446,8 @@ void ARMTargetLowering::emitAtomicCmpXchgNoStoreLLBalance( if (!Subtarget->hasV7Ops()) return; Module *M = Builder.GetInsertBlock()->getParent()->getParent(); - Builder.CreateCall(Intrinsic::getDeclaration(M, Intrinsic::arm_clrex)); + Builder.CreateCall( + Intrinsic::getOrInsertDeclaration(M, Intrinsic::arm_clrex)); } Value *ARMTargetLowering::emitStoreConditional(IRBuilderBase &Builder, @@ -21604,7 +21462,7 @@ Value *ARMTargetLowering::emitStoreConditional(IRBuilderBase &Builder, if (Val->getType()->getPrimitiveSizeInBits() == 64) { Intrinsic::ID Int = IsRelease ? Intrinsic::arm_stlexd : Intrinsic::arm_strexd; - Function *Strex = Intrinsic::getDeclaration(M, Int); + Function *Strex = Intrinsic::getOrInsertDeclaration(M, Int); Type *Int32Ty = Type::getInt32Ty(M->getContext()); Value *Lo = Builder.CreateTrunc(Val, Int32Ty, "lo"); @@ -21616,7 +21474,7 @@ Value *ARMTargetLowering::emitStoreConditional(IRBuilderBase &Builder, Intrinsic::ID Int = IsRelease ? Intrinsic::arm_stlex : Intrinsic::arm_strex; Type *Tys[] = { Addr->getType() }; - Function *Strex = Intrinsic::getDeclaration(M, Int, Tys); + Function *Strex = Intrinsic::getOrInsertDeclaration(M, Int, Tys); CallInst *CI = Builder.CreateCall( Strex, {Builder.CreateZExtOrBitCast( @@ -21744,8 +21602,8 @@ bool ARMTargetLowering::lowerInterleavedLoad( static const Intrinsic::ID LoadInts[3] = {Intrinsic::arm_neon_vld2, Intrinsic::arm_neon_vld3, Intrinsic::arm_neon_vld4}; - Function *VldnFunc = - Intrinsic::getDeclaration(LI->getModule(), LoadInts[Factor - 2], Tys); + Function *VldnFunc = Intrinsic::getOrInsertDeclaration( + LI->getModule(), LoadInts[Factor - 2], Tys); SmallVector<Value *, 2> Ops; Ops.push_back(BaseAddr); @@ -21760,7 +21618,7 @@ bool ARMTargetLowering::lowerInterleavedLoad( Type *PtrTy = Builder.getPtrTy(LI->getPointerAddressSpace()); Type *Tys[] = {VecTy, PtrTy}; Function *VldnFunc = - Intrinsic::getDeclaration(LI->getModule(), LoadInts, Tys); + Intrinsic::getOrInsertDeclaration(LI->getModule(), LoadInts, Tys); SmallVector<Value *, 2> Ops; Ops.push_back(BaseAddr); @@ -21905,7 +21763,7 @@ bool ARMTargetLowering::lowerInterleavedStore(StoreInst *SI, Type *PtrTy = Builder.getPtrTy(SI->getPointerAddressSpace()); Type *Tys[] = {PtrTy, SubVecTy}; - Function *VstNFunc = Intrinsic::getDeclaration( + Function *VstNFunc = Intrinsic::getOrInsertDeclaration( SI->getModule(), StoreInts[Factor - 2], Tys); SmallVector<Value *, 6> Ops; @@ -21921,7 +21779,7 @@ bool ARMTargetLowering::lowerInterleavedStore(StoreInst *SI, Type *PtrTy = Builder.getPtrTy(SI->getPointerAddressSpace()); Type *Tys[] = {PtrTy, SubVecTy}; Function *VstNFunc = - Intrinsic::getDeclaration(SI->getModule(), StoreInts, Tys); + Intrinsic::getOrInsertDeclaration(SI->getModule(), StoreInts, Tys); SmallVector<Value *, 6> Ops; Ops.push_back(BaseAddr); |
