LLVM 24.0.0git
ScopedNoAliasAA.cpp
Go to the documentation of this file.
1//===- ScopedNoAliasAA.cpp - Scoped No-Alias Alias Analysis ---------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines the ScopedNoAlias alias-analysis pass, which implements
10// metadata-based scoped no-alias support.
11//
12// Alias-analysis scopes are defined by an id (which can be a string or some
13// other metadata node), a domain node, and an optional descriptive string.
14// A domain is defined by an id (which can be a string or some other metadata
15// node), a flag saying whether its scopes are disjoint, and an optional
16// descriptive string.
17//
18// !dom0 = metadata !{ metadata !"domain of foo()", i1 false }
19// !scope1 = metadata !{ metadata !scope1, metadata !dom0, metadata !"scope 1" }
20// !scope2 = metadata !{ metadata !scope2, metadata !dom0, metadata !"scope 2" }
21//
22// Loads and stores can be tagged with an alias-analysis scope, and also, with
23// a noalias tag for a specific scope:
24//
25// ... = load %ptr1, !alias.scope !{ !scope1 }
26// ... = load %ptr2, !alias.scope !{ !scope1, !scope2 }, !noalias !{ !scope1 }
27//
28// When evaluating an aliasing query, if one of the instructions
29// has a set of noalias scopes in some domain that is a superset of the alias
30// scopes in that domain of some other instruction, then the two memory
31// accesses are assumed not to alias.
32//
33// If a domain is declared as having disjoint scopes, two memory accesses are
34// assumed not to alias if the they both have entries for that domain in their
35// `alias.scope` list and their `alias.scope` lists have no scopes in common for
36// that domain. Equivalently, an instruction with a set of scopes from a
37// disjoint-scope domain in its `alias.scope` list implicitly has all other
38// scopes in that domain in its `noalias` set. For example,
39//
40// !dom1 = metadata !{ metadata !dom1, i1 true, metadata !"disjoint domain" }
41// !scope3 = metadata !{ metadata !scope3, metadata !dom1 }
42// !scope4 = metadata !{ metadata !scope4, metadata !dom1 }
43//
44// ... = load %ptr3, !alias.scope !{ !scope3 } ; doesn't alias the load below
45// ... = load %ptr4, !alias.scope !{ !scope4 }
46//
47//===----------------------------------------------------------------------===//
48
50#include "AnalysisOptions.h"
54#include "llvm/IR/InstrTypes.h"
56#include "llvm/IR/LLVMContext.h"
57#include "llvm/IR/Metadata.h"
58#include "llvm/IR/Module.h"
60#include "llvm/Pass.h"
62
63using namespace llvm;
64
67
69 const MemoryLocation &LocB) {
70 if (!Opts.enable_scoped_noalias)
72
73 // Get the attached MDNodes.
74 const MDNode *AScopes = LocA.AATags.Scope, *BScopes = LocB.AATags.Scope;
75
76 const MDNode *ANoAlias = LocA.AATags.NoAlias, *BNoAlias = LocB.AATags.NoAlias;
77
78 if (!mayAliasInScopes(AScopes, BNoAlias))
80
81 if (!mayAliasInScopes(BScopes, ANoAlias))
83
84 if (!mayAliasInDisjointDomains(AScopes, BScopes))
86
88}
89
91 const MemoryLocation &LocB,
92 AAQueryInfo &, const Instruction *) {
93 return alias(LocA, LocB);
94}
95
97 const MemoryLocation &Loc,
98 AAQueryInfo &AAQI) {
99 if (!Opts.enable_scoped_noalias)
100 return ModRefInfo::ModRef;
101
102 if (!mayAliasInScopes(Loc.AATags.Scope,
103 Call->getMetadata(LLVMContext::MD_noalias)))
105
106 if (!mayAliasInScopes(Call->getMetadata(LLVMContext::MD_alias_scope),
107 Loc.AATags.NoAlias))
109
111 Loc.AATags.Scope, Call->getMetadata(LLVMContext::MD_alias_scope)))
113
114 return ModRefInfo::ModRef;
115}
116
118 const MemoryLocation &Loc,
119 AAQueryInfo &AAQI) {
120 if (!Opts.enable_scoped_noalias)
121 return ModRefInfo::ModRef;
122
123 if (!mayAliasInScopes(Loc.AATags.Scope,
124 F->getMetadata(LLVMContext::MD_noalias)))
126
127 if (!mayAliasInScopes(F->getMetadata(LLVMContext::MD_alias_scope),
128 Loc.AATags.NoAlias))
130
131 if (!mayAliasInDisjointDomains(Loc.AATags.Scope,
132 F->getMetadata(LLVMContext::MD_alias_scope)))
134
135 return ModRefInfo::ModRef;
136}
137
139 const CallBase *Call2,
140 AAQueryInfo &AAQI) {
141 if (!Opts.enable_scoped_noalias)
142 return ModRefInfo::ModRef;
143
144 if (!mayAliasInScopes(Call1->getMetadata(LLVMContext::MD_alias_scope),
145 Call2->getMetadata(LLVMContext::MD_noalias)))
147
148 if (!mayAliasInScopes(Call2->getMetadata(LLVMContext::MD_alias_scope),
149 Call1->getMetadata(LLVMContext::MD_noalias)))
151
153 Call1->getMetadata(LLVMContext::MD_alias_scope),
154 Call2->getMetadata(LLVMContext::MD_alias_scope)))
156
157 return ModRefInfo::ModRef;
158}
159
160static void collectMDInDomain(const MDNode *List, const MDNode *Domain,
162 for (const MDOperand &MDOp : List->operands())
163 if (const MDNode *MD = dyn_cast<MDNode>(MDOp))
164 if (AliasScopeNode(MD).getDomain() == Domain)
165 Nodes.insert(MD);
166}
167
168/// Collect the set of scoped domains relevant to the noalias scopes.
170 const MDNode *NoAlias, SmallPtrSetImpl<const MDNode *> &Domains,
171 bool DisjointOnly) {
172 if (!NoAlias)
173 return;
174 assert(Domains.empty() && "Domains should be empty");
175 for (const MDOperand &MDOp : NoAlias->operands())
176 if (const MDNode *NAMD = dyn_cast<MDNode>(MDOp))
177 if (const MDNode *Domain = AliasScopeNode(NAMD).getDomain())
178 if (!DisjointOnly || AliasScopeDomainNode(Domain).hasDisjointScopes())
179 Domains.insert(Domain);
180}
181
183 const MDNode *NoAlias) {
184 if (!Scopes || !NoAlias)
185 return true;
186
187 // Collect the set of scope domains relevant to the noalias scopes.
189 collectScopedDomains(NoAlias, Domains);
190
191 // We alias unless, for some domain, the set of noalias scopes in that domain
192 // is a superset of the set of alias scopes in that domain.
193 for (const MDNode *Domain : Domains) {
195 collectMDInDomain(Scopes, Domain, ScopeNodes);
196 if (ScopeNodes.empty())
197 continue;
198
200 collectMDInDomain(NoAlias, Domain, NANodes);
201
202 // To not alias, all of the nodes in ScopeNodes must be in NANodes.
203 if (llvm::set_is_subset(ScopeNodes, NANodes))
204 return false;
205 }
206
207 return true;
208}
209
211 const MDNode *Scopes2) {
212 if (!Scopes1 || !Scopes2)
213 return true;
214
215 // Collect the domains with disjoint scopes that the first access is in.
217 collectScopedDomains(Scopes1, Domains, /*DisjointOnly=*/true);
218
219 // The accesses don't alias if, for some domain, both accesses use at least
220 // one of its scopes and have no scopes in that domain in common.
221 for (const MDNode *Domain : Domains) {
223 collectMDInDomain(Scopes2, Domain, Nodes2);
224 if (Nodes2.empty())
225 continue;
226
228 collectMDInDomain(Scopes1, Domain, Nodes1);
229 if (!llvm::set_intersects(Nodes1, Nodes2))
230 return false;
231 }
232
233 return true;
234}
235
236AnalysisKey ScopedNoAliasAA::Key;
237
242
244
246 "Scoped NoAlias Alias Analysis", false, true)
247
249 return new ScopedNoAliasAAWrapperPass();
250}
251
253
255 Result.reset(new ScopedNoAliasAAResult(M.getContext()));
256 return false;
257}
258
260 Result.reset();
261 return false;
262}
263
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static Domain getDomain(const ConstantRange &CR)
Module.h This file contains the declarations for the Module class.
#define F(x, y, z)
Definition MD5.cpp:54
This file provides utility analysis objects describing memory locations.
This file contains the declarations for metadata subclasses.
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
static void collectMDInDomain(const MDNode *List, const MDNode *Domain, SmallPtrSetImpl< const MDNode * > &Nodes)
This is the interface for a metadata-based scoped no-alias analysis.
This file defines generic set operations that may be used on set's of different types,...
This file defines the SmallPtrSet class.
This class stores info we want to provide to or retain within an alias query.
The possible results of an alias query.
@ MayAlias
The two locations may or may not alias.
@ NoAlias
The two locations do not alias at all.
Wrapper around alias scope domain metedata to allow accessing their fields, including surfacing the o...
Definition Metadata.h:1603
This is a simple wrapper around an MDNode which provides a higher-level interface by hiding the detai...
Definition Metadata.h:1633
Represent the analysis usage information of a pass.
void setPreservesAll()
Set by analyses that do not transform their input at all.
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
An instruction for ordering other memory operations.
ImmutablePass class - This class is used to provide information that does not need to be run.
Definition Pass.h:283
ImmutablePass(char &pid)
Definition Pass.h:285
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this Instruction.
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:76
Metadata node.
Definition Metadata.h:1081
ArrayRef< MDOperand > operands() const
Definition Metadata.h:1435
Tracking metadata reference owned by Metadata.
Definition Metadata.h:902
Representation for a specific memory location.
AAMDNodes AATags
The metadata nodes which describes the aliasing of the location (each member is null if that kind of ...
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:68
A simple AA result which uses scoped-noalias metadata to answer queries.
static LLVM_ABI bool mayAliasInScopes(const MDNode *Scopes, const MDNode *NoAlias)
LLVM_ABI AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB)
LLVM_ABI ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc, AAQueryInfo &AAQI)
LLVM_ABI ScopedNoAliasAAResult(const LLVMContext &C)
static LLVM_ABI void collectScopedDomains(const MDNode *NoAlias, SmallPtrSetImpl< const MDNode * > &Domains, bool DisjointOnly=false)
Collect the set of scoped domains relevant to the noalias scopes.
static LLVM_ABI bool mayAliasInDisjointDomains(const MDNode *Scopes1, const MDNode *Scopes2)
Return false if two accesses with scope lists Scopes1 and Scopes2 are kept apart because they use dif...
Legacy wrapper pass to provide the ScopedNoAliasAAResult object.
bool doInitialization(Module &M) override
doInitialization - Virtual method overridden by subclasses to do any necessary initialization before ...
bool doFinalization(Module &M) override
doFinalization - Virtual method overriden by subclasses to do any necessary clean up after all passes...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
LLVM_ABI ScopedNoAliasAAResult run(Function &F, FunctionAnalysisManager &AM)
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
CallInst * Call
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
bool set_is_subset(const S1Ty &S1, const S2Ty &S2)
set_is_subset(A, B) - Return true iff A in B
bool set_intersects(const S1Ty &S1, const S2Ty &S2)
set_intersects(A, B) - Return true iff A ^ B is non empty
const AnalysisOptions & getAnalysisOptions(const LLVMContext &C)
LLVM_ABI ImmutablePass * createScopedNoAliasAAWrapperPass()
ModRefInfo
Flags indicating whether a memory access modifies or references memory.
Definition ModRef.h:28
@ ModRef
The access may reference and may modify the value stored in memory.
Definition ModRef.h:36
@ NoModRef
The access neither references nor modifies the value stored in memory.
Definition ModRef.h:30
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
MDNode * Scope
The tag for alias scope specification (used with noalias).
Definition Metadata.h:797
MDNode * NoAlias
The tag specifying the noalias scope.
Definition Metadata.h:800
A special type used by analysis passes to provide an address that identifies that particular analysis...
Definition Analysis.h:29