diff --git a/llvm/include/llvm/IR/InstrTypes.h b/llvm/include/llvm/IR/InstrTypes.h --- a/llvm/include/llvm/IR/InstrTypes.h +++ b/llvm/include/llvm/IR/InstrTypes.h @@ -25,6 +25,7 @@ #include "llvm/ADT/iterator_range.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/CallingConv.h" +#include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Function.h" #include "llvm/IR/Instruction.h" @@ -1613,12 +1614,16 @@ /// Get the attribute of a given kind for the function. Attribute getFnAttr(StringRef Kind) const { - return getAttributes().getFnAttr(Kind); + if (Attrs.hasFnAttr(Kind)) + return getAttributes().getFnAttr(Kind); + return getFnAttrOnCalledFunction(Kind); } /// Get the attribute of a given kind for the function. Attribute getFnAttr(Attribute::AttrKind Kind) const { - return getAttributes().getFnAttr(Kind); + if (Attrs.hasFnAttr(Kind)) + return getAttributes().getFnAttr(Kind); + return getFnAttrOnCalledFunction(Kind); } /// Get the attribute of a given kind from a given arg @@ -2300,6 +2305,22 @@ bool hasFnAttrOnCalledFunction(Attribute::AttrKind Kind) const; bool hasFnAttrOnCalledFunction(StringRef Kind) const; + template Attribute getFnAttrOnCalledFunction(AK Kind) const { + // Operand bundles override attributes on the called function, but don't + // override attributes directly present on the call instruction. + if (isFnAttrDisallowedByOpBundle(Kind)) + return Attribute(); + Value *V = getCalledOperand(); + if (auto *CE = dyn_cast(V)) + if (CE->getOpcode() == BitCast) + V = CE->getOperand(0); + + if (auto *F = dyn_cast(V)) + return F->getAttributes().getFnAttr(Kind); + + return Attribute(); + } + template bool hasFnAttrImpl(AttrKind Kind) const { if (Attrs.hasFnAttr(Kind)) return true;