AliasAnalysisSummary.cpp revision 355940
1#include "AliasAnalysisSummary.h"
2#include "llvm/IR/Argument.h"
3#include "llvm/IR/Type.h"
4#include "llvm/Support/Compiler.h"
5
6namespace llvm {
7namespace cflaa {
8
9namespace {
10const unsigned AttrEscapedIndex = 0;
11const unsigned AttrUnknownIndex = 1;
12const unsigned AttrGlobalIndex = 2;
13const unsigned AttrCallerIndex = 3;
14const unsigned AttrFirstArgIndex = 4;
15const unsigned AttrLastArgIndex = NumAliasAttrs;
16const unsigned AttrMaxNumArgs = AttrLastArgIndex - AttrFirstArgIndex;
17
18// It would be *slightly* prettier if we changed these to AliasAttrs, but it
19// seems that both GCC and MSVC emit dynamic initializers for const bitsets.
20using AliasAttr = unsigned;
21const AliasAttr AttrNone = 0;
22const AliasAttr AttrEscaped = 1 << AttrEscapedIndex;
23const AliasAttr AttrUnknown = 1 << AttrUnknownIndex;
24const AliasAttr AttrGlobal = 1 << AttrGlobalIndex;
25const AliasAttr AttrCaller = 1 << AttrCallerIndex;
26const AliasAttr ExternalAttrMask = AttrEscaped | AttrUnknown | AttrGlobal;
27}
28
29AliasAttrs getAttrNone() { return AttrNone; }
30
31AliasAttrs getAttrUnknown() { return AttrUnknown; }
32bool hasUnknownAttr(AliasAttrs Attr) { return Attr.test(AttrUnknownIndex); }
33
34AliasAttrs getAttrCaller() { return AttrCaller; }
35bool hasCallerAttr(AliasAttrs Attr) { return Attr.test(AttrCaller); }
36bool hasUnknownOrCallerAttr(AliasAttrs Attr) {
37  return Attr.test(AttrUnknownIndex) || Attr.test(AttrCallerIndex);
38}
39
40AliasAttrs getAttrEscaped() { return AttrEscaped; }
41bool hasEscapedAttr(AliasAttrs Attr) { return Attr.test(AttrEscapedIndex); }
42
43static AliasAttr argNumberToAttr(unsigned ArgNum) {
44  if (ArgNum >= AttrMaxNumArgs)
45    return AttrUnknown;
46  // N.B. MSVC complains if we use `1U` here, since AliasAttr' ctor takes
47  // an unsigned long long.
48  return AliasAttr(1ULL << (ArgNum + AttrFirstArgIndex));
49}
50
51AliasAttrs getGlobalOrArgAttrFromValue(const Value &Val) {
52  if (isa<GlobalValue>(Val))
53    return AttrGlobal;
54
55  if (auto *Arg = dyn_cast<Argument>(&Val))
56    // Only pointer arguments should have the argument attribute,
57    // because things can't escape through scalars without us seeing a
58    // cast, and thus, interaction with them doesn't matter.
59    if (!Arg->hasNoAliasAttr() && Arg->getType()->isPointerTy())
60      return argNumberToAttr(Arg->getArgNo());
61  return AttrNone;
62}
63
64bool isGlobalOrArgAttr(AliasAttrs Attr) {
65  return Attr.reset(AttrEscapedIndex)
66      .reset(AttrUnknownIndex)
67      .reset(AttrCallerIndex)
68      .any();
69}
70
71AliasAttrs getExternallyVisibleAttrs(AliasAttrs Attr) {
72  return Attr & AliasAttrs(ExternalAttrMask);
73}
74
75Optional<InstantiatedValue> instantiateInterfaceValue(InterfaceValue IValue,
76                                                      CallBase &Call) {
77  auto Index = IValue.Index;
78  auto *V = (Index == 0) ? &Call : Call.getArgOperand(Index - 1);
79  if (V->getType()->isPointerTy())
80    return InstantiatedValue{V, IValue.DerefLevel};
81  return None;
82}
83
84Optional<InstantiatedRelation>
85instantiateExternalRelation(ExternalRelation ERelation, CallBase &Call) {
86  auto From = instantiateInterfaceValue(ERelation.From, Call);
87  if (!From)
88    return None;
89  auto To = instantiateInterfaceValue(ERelation.To, Call);
90  if (!To)
91    return None;
92  return InstantiatedRelation{*From, *To, ERelation.Offset};
93}
94
95Optional<InstantiatedAttr> instantiateExternalAttribute(ExternalAttribute EAttr,
96                                                        CallBase &Call) {
97  auto Value = instantiateInterfaceValue(EAttr.IValue, Call);
98  if (!Value)
99    return None;
100  return InstantiatedAttr{*Value, EAttr.Attr};
101}
102}
103}
104