[OperandBundles] Allow operand-specific attributes in operand bundles
Currently `OperandBundleUse::operandsHaveAttr` computes its result
without being given a specific operand. This is problematic because it
forces us to say that, e.g., even non-pointer operands in `"deopt"`
operand bundles are `readonly`, which doesn't make sense.
This commit changes `operandsHaveAttr` to work in the context of a
specific operand, so that we can give the operand attributes that make
sense for the operands's `llvm::Type`.
llvm-svn: 254764
diff --git a/llvm/include/llvm/IR/InstrTypes.h b/llvm/include/llvm/IR/InstrTypes.h
index 81de699..58bc7c1 100644
--- a/llvm/include/llvm/IR/InstrTypes.h
+++ b/llvm/include/llvm/IR/InstrTypes.h
@@ -1121,14 +1121,12 @@
explicit OperandBundleUse(StringMapEntry<uint32_t> *Tag, ArrayRef<Use> Inputs)
: Inputs(Inputs), Tag(Tag) {}
- /// \brief Return true if all the operands in this operand bundle have the
- /// attribute A.
- ///
- /// Currently there is no way to have attributes on operand bundles differ on
- /// a per operand granularity.
- bool operandsHaveAttr(Attribute::AttrKind A) const {
+ /// \brief Return true if the operand at index \p Idx in this operand bundle
+ /// has the attribute A.
+ bool operandHasAttr(unsigned Idx, Attribute::AttrKind A) const {
if (isDeoptOperandBundle())
- return A == Attribute::ReadOnly || A == Attribute::NoCapture;
+ if (A == Attribute::ReadOnly || A == Attribute::NoCapture)
+ return Inputs[Idx]->getType()->isPointerTy();
// Conservative answer: no operands have any attributes.
return false;
@@ -1351,11 +1349,7 @@
/// It is an error to call this with an OpIdx that does not correspond to an
/// bundle operand.
OperandBundleUse getOperandBundleForOperand(unsigned OpIdx) const {
- for (auto &BOI : bundle_op_infos())
- if (BOI.Begin <= OpIdx && OpIdx < BOI.End)
- return operandBundleFromBundleOpInfo(BOI);
-
- llvm_unreachable("Did not find operand bundle for operand!");
+ return operandBundleFromBundleOpInfo(getBundleOpInfoForOperand(OpIdx));
}
/// \brief Return true if this operand bundle user has operand bundles that
@@ -1382,6 +1376,14 @@
return false;
}
+ /// \brief Return true if the bundle operand at index \p OpIdx has the
+ /// attribute \p A.
+ bool bundleOperandHasAttr(unsigned OpIdx, Attribute::AttrKind A) const {
+ auto &BOI = getBundleOpInfoForOperand(OpIdx);
+ auto OBU = operandBundleFromBundleOpInfo(BOI);
+ return OBU.operandHasAttr(OpIdx - BOI.Begin, A);
+ }
+
protected:
/// \brief Is the function attribute S disallowed by some operand bundle on
/// this operand bundle user?
@@ -1518,6 +1520,18 @@
return It;
}
+ /// \brief Return the BundleOpInfo for the operand at index OpIdx.
+ ///
+ /// It is an error to call this with an OpIdx that does not correspond to an
+ /// bundle operand.
+ const BundleOpInfo &getBundleOpInfoForOperand(unsigned OpIdx) const {
+ for (auto &BOI : bundle_op_infos())
+ if (BOI.Begin <= OpIdx && OpIdx < BOI.End)
+ return BOI;
+
+ llvm_unreachable("Did not find operand bundle for operand!");
+ }
+
/// \brief Return the total number of values used in \p Bundles.
static unsigned CountBundleInputs(ArrayRef<OperandBundleDef> Bundles) {
unsigned Total = 0;
diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp
index b8c72dd..bba0ef2 100644
--- a/llvm/lib/IR/Instructions.cpp
+++ b/llvm/lib/IR/Instructions.cpp
@@ -369,7 +369,7 @@
assert(hasOperandBundles() && i >= (getBundleOperandsStartIndex() + 1) &&
"Must be either a call argument or an operand bundle!");
- return getOperandBundleForOperand(i - 1).operandsHaveAttr(A);
+ return bundleOperandHasAttr(i - 1, A);
}
/// IsConstantOne - Return true only if val is constant int 1
@@ -646,7 +646,7 @@
assert(hasOperandBundles() && i >= (getBundleOperandsStartIndex() + 1) &&
"Must be either an invoke argument or an operand bundle!");
- return getOperandBundleForOperand(i - 1).operandsHaveAttr(A);
+ return bundleOperandHasAttr(i - 1, A);
}
void InvokeInst::addAttribute(unsigned i, Attribute::AttrKind attr) {