diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2022-03-20 11:40:34 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2022-06-04 11:58:51 +0000 |
| commit | 4b6eb0e63c698094db5506763df44cc83c19f643 (patch) | |
| tree | f1d30b8c10bc6db323b91538745ae8ab8b593910 /contrib/llvm-project/llvm/lib/IR/Instructions.cpp | |
| parent | 76886853f03395abb680824bcc74e98f83bd477a (diff) | |
Diffstat (limited to 'contrib/llvm-project/llvm/lib/IR/Instructions.cpp')
| -rw-r--r-- | contrib/llvm-project/llvm/lib/IR/Instructions.cpp | 248 |
1 files changed, 234 insertions, 14 deletions
diff --git a/contrib/llvm-project/llvm/lib/IR/Instructions.cpp b/contrib/llvm-project/llvm/lib/IR/Instructions.cpp index 5b01c70dec8d..c42df49d97ea 100644 --- a/contrib/llvm-project/llvm/lib/IR/Instructions.cpp +++ b/contrib/llvm-project/llvm/lib/IR/Instructions.cpp @@ -318,9 +318,8 @@ bool CallBase::isReturnNonNull() const { if (hasRetAttr(Attribute::NonNull)) return true; - if (getDereferenceableBytes(AttributeList::ReturnIndex) > 0 && - !NullPointerIsDefined(getCaller(), - getType()->getPointerAddressSpace())) + if (getRetDereferenceableBytes() > 0 && + !NullPointerIsDefined(getCaller(), getType()->getPointerAddressSpace())) return true; return false; @@ -329,11 +328,10 @@ bool CallBase::isReturnNonNull() const { Value *CallBase::getReturnedArgOperand() const { unsigned Index; - if (Attrs.hasAttrSomewhere(Attribute::Returned, &Index) && Index) + if (Attrs.hasAttrSomewhere(Attribute::Returned, &Index)) return getArgOperand(Index - AttributeList::FirstArgIndex); if (const Function *F = getCalledFunction()) - if (F->getAttributes().hasAttrSomewhere(Attribute::Returned, &Index) && - Index) + if (F->getAttributes().hasAttrSomewhere(Attribute::Returned, &Index)) return getArgOperand(Index - AttributeList::FirstArgIndex); return nullptr; @@ -341,24 +339,36 @@ Value *CallBase::getReturnedArgOperand() const { /// Determine whether the argument or parameter has the given attribute. bool CallBase::paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const { - assert(ArgNo < getNumArgOperands() && "Param index out of bounds!"); + assert(ArgNo < arg_size() && "Param index out of bounds!"); - if (Attrs.hasParamAttribute(ArgNo, Kind)) + if (Attrs.hasParamAttr(ArgNo, Kind)) return true; if (const Function *F = getCalledFunction()) - return F->getAttributes().hasParamAttribute(ArgNo, Kind); + return F->getAttributes().hasParamAttr(ArgNo, Kind); return false; } bool CallBase::hasFnAttrOnCalledFunction(Attribute::AttrKind Kind) const { - if (const Function *F = getCalledFunction()) - return F->getAttributes().hasFnAttribute(Kind); + Value *V = getCalledOperand(); + if (auto *CE = dyn_cast<ConstantExpr>(V)) + if (CE->getOpcode() == BitCast) + V = CE->getOperand(0); + + if (auto *F = dyn_cast<Function>(V)) + return F->getAttributes().hasFnAttr(Kind); + return false; } bool CallBase::hasFnAttrOnCalledFunction(StringRef Kind) const { - if (const Function *F = getCalledFunction()) - return F->getAttributes().hasFnAttribute(Kind); + Value *V = getCalledOperand(); + if (auto *CE = dyn_cast<ConstantExpr>(V)) + if (CE->getOpcode() == BitCast) + V = CE->getOperand(0); + + if (auto *F = dyn_cast<Function>(V)) + return F->getAttributes().hasFnAttr(Kind); + return false; } @@ -933,7 +943,7 @@ void CallBrInst::updateArgBlockAddresses(unsigned i, BasicBlock *B) { if (BasicBlock *OldBB = getIndirectDest(i)) { BlockAddress *Old = BlockAddress::get(OldBB); BlockAddress *New = BlockAddress::get(B); - for (unsigned ArgNo = 0, e = getNumArgOperands(); ArgNo != e; ++ArgNo) + for (unsigned ArgNo = 0, e = arg_size(); ArgNo != e; ++ArgNo) if (dyn_cast<BlockAddress>(getArgOperand(ArgNo)) == Old) setArgOperand(ArgNo, New); } @@ -1909,6 +1919,32 @@ bool InsertElementInst::isValidOperands(const Value *Vec, const Value *Elt, // ShuffleVectorInst Implementation //===----------------------------------------------------------------------===// +static Value *createPlaceholderForShuffleVector(Value *V) { + assert(V && "Cannot create placeholder of nullptr V"); + return PoisonValue::get(V->getType()); +} + +ShuffleVectorInst::ShuffleVectorInst(Value *V1, Value *Mask, const Twine &Name, + Instruction *InsertBefore) + : ShuffleVectorInst(V1, createPlaceholderForShuffleVector(V1), Mask, Name, + InsertBefore) {} + +ShuffleVectorInst::ShuffleVectorInst(Value *V1, Value *Mask, const Twine &Name, + BasicBlock *InsertAtEnd) + : ShuffleVectorInst(V1, createPlaceholderForShuffleVector(V1), Mask, Name, + InsertAtEnd) {} + +ShuffleVectorInst::ShuffleVectorInst(Value *V1, ArrayRef<int> Mask, + const Twine &Name, + Instruction *InsertBefore) + : ShuffleVectorInst(V1, createPlaceholderForShuffleVector(V1), Mask, Name, + InsertBefore) {} + +ShuffleVectorInst::ShuffleVectorInst(Value *V1, ArrayRef<int> Mask, + const Twine &Name, BasicBlock *InsertAtEnd) + : ShuffleVectorInst(V1, createPlaceholderForShuffleVector(V1), Mask, Name, + InsertAtEnd) {} + ShuffleVectorInst::ShuffleVectorInst(Value *V1, Value *V2, Value *Mask, const Twine &Name, Instruction *InsertBefore) @@ -2259,6 +2295,80 @@ bool ShuffleVectorInst::isExtractSubvectorMask(ArrayRef<int> Mask, return false; } +bool ShuffleVectorInst::isInsertSubvectorMask(ArrayRef<int> Mask, + int NumSrcElts, int &NumSubElts, + int &Index) { + int NumMaskElts = Mask.size(); + + // Don't try to match if we're shuffling to a smaller size. + if (NumMaskElts < NumSrcElts) + return false; + + // TODO: We don't recognize self-insertion/widening. + if (isSingleSourceMaskImpl(Mask, NumSrcElts)) + return false; + + // Determine which mask elements are attributed to which source. + APInt UndefElts = APInt::getZero(NumMaskElts); + APInt Src0Elts = APInt::getZero(NumMaskElts); + APInt Src1Elts = APInt::getZero(NumMaskElts); + bool Src0Identity = true; + bool Src1Identity = true; + + for (int i = 0; i != NumMaskElts; ++i) { + int M = Mask[i]; + if (M < 0) { + UndefElts.setBit(i); + continue; + } + if (M < NumSrcElts) { + Src0Elts.setBit(i); + Src0Identity &= (M == i); + continue; + } + Src1Elts.setBit(i); + Src1Identity &= (M == (i + NumSrcElts)); + continue; + } + assert((Src0Elts | Src1Elts | UndefElts).isAllOnes() && + "unknown shuffle elements"); + assert(!Src0Elts.isZero() && !Src1Elts.isZero() && + "2-source shuffle not found"); + + // Determine lo/hi span ranges. + // TODO: How should we handle undefs at the start of subvector insertions? + int Src0Lo = Src0Elts.countTrailingZeros(); + int Src1Lo = Src1Elts.countTrailingZeros(); + int Src0Hi = NumMaskElts - Src0Elts.countLeadingZeros(); + int Src1Hi = NumMaskElts - Src1Elts.countLeadingZeros(); + + // If src0 is in place, see if the src1 elements is inplace within its own + // span. + if (Src0Identity) { + int NumSub1Elts = Src1Hi - Src1Lo; + ArrayRef<int> Sub1Mask = Mask.slice(Src1Lo, NumSub1Elts); + if (isIdentityMaskImpl(Sub1Mask, NumSrcElts)) { + NumSubElts = NumSub1Elts; + Index = Src1Lo; + return true; + } + } + + // If src1 is in place, see if the src0 elements is inplace within its own + // span. + if (Src1Identity) { + int NumSub0Elts = Src0Hi - Src0Lo; + ArrayRef<int> Sub0Mask = Mask.slice(Src0Lo, NumSub0Elts); + if (isIdentityMaskImpl(Sub0Mask, NumSrcElts)) { + NumSubElts = NumSub0Elts; + Index = Src0Lo; + return true; + } + } + + return false; +} + bool ShuffleVectorInst::isIdentityWithPadding() const { if (isa<UndefValue>(Op<2>())) return false; @@ -2326,6 +2436,87 @@ bool ShuffleVectorInst::isConcat() const { return isIdentityMaskImpl(getShuffleMask(), NumMaskElts); } +static bool isReplicationMaskWithParams(ArrayRef<int> Mask, + int ReplicationFactor, int VF) { + assert(Mask.size() == (unsigned)ReplicationFactor * VF && + "Unexpected mask size."); + + for (int CurrElt : seq(0, VF)) { + ArrayRef<int> CurrSubMask = Mask.take_front(ReplicationFactor); + assert(CurrSubMask.size() == (unsigned)ReplicationFactor && + "Run out of mask?"); + Mask = Mask.drop_front(ReplicationFactor); + if (!all_of(CurrSubMask, [CurrElt](int MaskElt) { + return MaskElt == UndefMaskElem || MaskElt == CurrElt; + })) + return false; + } + assert(Mask.empty() && "Did not consume the whole mask?"); + + return true; +} + +bool ShuffleVectorInst::isReplicationMask(ArrayRef<int> Mask, + int &ReplicationFactor, int &VF) { + // undef-less case is trivial. + if (none_of(Mask, [](int MaskElt) { return MaskElt == UndefMaskElem; })) { + ReplicationFactor = + Mask.take_while([](int MaskElt) { return MaskElt == 0; }).size(); + if (ReplicationFactor == 0 || Mask.size() % ReplicationFactor != 0) + return false; + VF = Mask.size() / ReplicationFactor; + return isReplicationMaskWithParams(Mask, ReplicationFactor, VF); + } + + // However, if the mask contains undef's, we have to enumerate possible tuples + // and pick one. There are bounds on replication factor: [1, mask size] + // (where RF=1 is an identity shuffle, RF=mask size is a broadcast shuffle) + // Additionally, mask size is a replication factor multiplied by vector size, + // which further significantly reduces the search space. + + // Before doing that, let's perform basic sanity check first. + int Largest = -1; + for (int MaskElt : Mask) { + if (MaskElt == UndefMaskElem) + continue; + // Elements must be in non-decreasing order. + if (MaskElt < Largest) + return false; + Largest = std::max(Largest, MaskElt); + } + + // Prefer larger replication factor if all else equal. + for (int PossibleReplicationFactor : + reverse(seq_inclusive<unsigned>(1, Mask.size()))) { + if (Mask.size() % PossibleReplicationFactor != 0) + continue; + int PossibleVF = Mask.size() / PossibleReplicationFactor; + if (!isReplicationMaskWithParams(Mask, PossibleReplicationFactor, + PossibleVF)) + continue; + ReplicationFactor = PossibleReplicationFactor; + VF = PossibleVF; + return true; + } + + return false; +} + +bool ShuffleVectorInst::isReplicationMask(int &ReplicationFactor, + int &VF) const { + // Not possible to express a shuffle mask for a scalable vector for this + // case. + if (isa<ScalableVectorType>(getType())) + return false; + + VF = cast<FixedVectorType>(Op<0>()->getType())->getNumElements(); + if (ShuffleMask.size() % VF != 0) + return false; + ReplicationFactor = ShuffleMask.size() / VF; + + return isReplicationMaskWithParams(ShuffleMask, ReplicationFactor, VF); +} + //===----------------------------------------------------------------------===// // InsertValueInst Class //===----------------------------------------------------------------------===// @@ -3945,6 +4136,35 @@ bool CmpInst::isSigned(Predicate predicate) { } } +bool ICmpInst::compare(const APInt &LHS, const APInt &RHS, + ICmpInst::Predicate Pred) { + assert(ICmpInst::isIntPredicate(Pred) && "Only for integer predicates!"); + switch (Pred) { + case ICmpInst::Predicate::ICMP_EQ: + return LHS.eq(RHS); + case ICmpInst::Predicate::ICMP_NE: + return LHS.ne(RHS); + case ICmpInst::Predicate::ICMP_UGT: + return LHS.ugt(RHS); + case ICmpInst::Predicate::ICMP_UGE: + return LHS.uge(RHS); + case ICmpInst::Predicate::ICMP_ULT: + return LHS.ult(RHS); + case ICmpInst::Predicate::ICMP_ULE: + return LHS.ule(RHS); + case ICmpInst::Predicate::ICMP_SGT: + return LHS.sgt(RHS); + case ICmpInst::Predicate::ICMP_SGE: + return LHS.sge(RHS); + case ICmpInst::Predicate::ICMP_SLT: + return LHS.slt(RHS); + case ICmpInst::Predicate::ICMP_SLE: + return LHS.sle(RHS); + default: + llvm_unreachable("Unexpected non-integer predicate."); + }; +} + CmpInst::Predicate CmpInst::getFlippedSignednessPredicate(Predicate pred) { assert(CmpInst::isRelational(pred) && "Call only with non-equality predicates!"); |
