diff options
Diffstat (limited to 'llvm/lib/Analysis/AliasAnalysisSummary.cpp')
| -rw-r--r-- | llvm/lib/Analysis/AliasAnalysisSummary.cpp | 103 | 
1 files changed, 103 insertions, 0 deletions
diff --git a/llvm/lib/Analysis/AliasAnalysisSummary.cpp b/llvm/lib/Analysis/AliasAnalysisSummary.cpp new file mode 100644 index 0000000000000..2f3396a44117a --- /dev/null +++ b/llvm/lib/Analysis/AliasAnalysisSummary.cpp @@ -0,0 +1,103 @@ +#include "AliasAnalysisSummary.h" +#include "llvm/IR/Argument.h" +#include "llvm/IR/Type.h" +#include "llvm/Support/Compiler.h" + +namespace llvm { +namespace cflaa { + +namespace { +const unsigned AttrEscapedIndex = 0; +const unsigned AttrUnknownIndex = 1; +const unsigned AttrGlobalIndex = 2; +const unsigned AttrCallerIndex = 3; +const unsigned AttrFirstArgIndex = 4; +const unsigned AttrLastArgIndex = NumAliasAttrs; +const unsigned AttrMaxNumArgs = AttrLastArgIndex - AttrFirstArgIndex; + +// It would be *slightly* prettier if we changed these to AliasAttrs, but it +// seems that both GCC and MSVC emit dynamic initializers for const bitsets. +using AliasAttr = unsigned; +const AliasAttr AttrNone = 0; +const AliasAttr AttrEscaped = 1 << AttrEscapedIndex; +const AliasAttr AttrUnknown = 1 << AttrUnknownIndex; +const AliasAttr AttrGlobal = 1 << AttrGlobalIndex; +const AliasAttr AttrCaller = 1 << AttrCallerIndex; +const AliasAttr ExternalAttrMask = AttrEscaped | AttrUnknown | AttrGlobal; +} + +AliasAttrs getAttrNone() { return AttrNone; } + +AliasAttrs getAttrUnknown() { return AttrUnknown; } +bool hasUnknownAttr(AliasAttrs Attr) { return Attr.test(AttrUnknownIndex); } + +AliasAttrs getAttrCaller() { return AttrCaller; } +bool hasCallerAttr(AliasAttrs Attr) { return Attr.test(AttrCaller); } +bool hasUnknownOrCallerAttr(AliasAttrs Attr) { +  return Attr.test(AttrUnknownIndex) || Attr.test(AttrCallerIndex); +} + +AliasAttrs getAttrEscaped() { return AttrEscaped; } +bool hasEscapedAttr(AliasAttrs Attr) { return Attr.test(AttrEscapedIndex); } + +static AliasAttr argNumberToAttr(unsigned ArgNum) { +  if (ArgNum >= AttrMaxNumArgs) +    return AttrUnknown; +  // N.B. MSVC complains if we use `1U` here, since AliasAttr' ctor takes +  // an unsigned long long. +  return AliasAttr(1ULL << (ArgNum + AttrFirstArgIndex)); +} + +AliasAttrs getGlobalOrArgAttrFromValue(const Value &Val) { +  if (isa<GlobalValue>(Val)) +    return AttrGlobal; + +  if (auto *Arg = dyn_cast<Argument>(&Val)) +    // Only pointer arguments should have the argument attribute, +    // because things can't escape through scalars without us seeing a +    // cast, and thus, interaction with them doesn't matter. +    if (!Arg->hasNoAliasAttr() && Arg->getType()->isPointerTy()) +      return argNumberToAttr(Arg->getArgNo()); +  return AttrNone; +} + +bool isGlobalOrArgAttr(AliasAttrs Attr) { +  return Attr.reset(AttrEscapedIndex) +      .reset(AttrUnknownIndex) +      .reset(AttrCallerIndex) +      .any(); +} + +AliasAttrs getExternallyVisibleAttrs(AliasAttrs Attr) { +  return Attr & AliasAttrs(ExternalAttrMask); +} + +Optional<InstantiatedValue> instantiateInterfaceValue(InterfaceValue IValue, +                                                      CallBase &Call) { +  auto Index = IValue.Index; +  auto *V = (Index == 0) ? &Call : Call.getArgOperand(Index - 1); +  if (V->getType()->isPointerTy()) +    return InstantiatedValue{V, IValue.DerefLevel}; +  return None; +} + +Optional<InstantiatedRelation> +instantiateExternalRelation(ExternalRelation ERelation, CallBase &Call) { +  auto From = instantiateInterfaceValue(ERelation.From, Call); +  if (!From) +    return None; +  auto To = instantiateInterfaceValue(ERelation.To, Call); +  if (!To) +    return None; +  return InstantiatedRelation{*From, *To, ERelation.Offset}; +} + +Optional<InstantiatedAttr> instantiateExternalAttribute(ExternalAttribute EAttr, +                                                        CallBase &Call) { +  auto Value = instantiateInterfaceValue(EAttr.IValue, Call); +  if (!Value) +    return None; +  return InstantiatedAttr{*Value, EAttr.Attr}; +} +} +}  | 
