aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/IR/Instructions.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2022-03-20 11:40:34 +0000
committerDimitry Andric <dim@FreeBSD.org>2022-06-04 11:58:51 +0000
commit4b6eb0e63c698094db5506763df44cc83c19f643 (patch)
treef1d30b8c10bc6db323b91538745ae8ab8b593910 /contrib/llvm-project/llvm/lib/IR/Instructions.cpp
parent76886853f03395abb680824bcc74e98f83bd477a (diff)
Diffstat (limited to 'contrib/llvm-project/llvm/lib/IR/Instructions.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/IR/Instructions.cpp248
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!");