-
Notifications
You must be signed in to change notification settings - Fork 143
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'development' into out-of-tree
Showing
15 changed files
with
3,775 additions
and
128 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,278 @@ | ||
============================================================================== | ||
The LLVM Project is under the Apache License v2.0 with LLVM Exceptions: | ||
============================================================================== | ||
|
||
Apache License | ||
Version 2.0, January 2004 | ||
http://www.apache.org/licenses/ | ||
|
||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | ||
|
||
1. Definitions. | ||
|
||
"License" shall mean the terms and conditions for use, reproduction, | ||
and distribution as defined by Sections 1 through 9 of this document. | ||
|
||
"Licensor" shall mean the copyright owner or entity authorized by | ||
the copyright owner that is granting the License. | ||
|
||
"Legal Entity" shall mean the union of the acting entity and all | ||
other entities that control, are controlled by, or are under common | ||
control with that entity. For the purposes of this definition, | ||
"control" means (i) the power, direct or indirect, to cause the | ||
direction or management of such entity, whether by contract or | ||
otherwise, or (ii) ownership of fifty percent (50%) or more of the | ||
outstanding shares, or (iii) beneficial ownership of such entity. | ||
|
||
"You" (or "Your") shall mean an individual or Legal Entity | ||
exercising permissions granted by this License. | ||
|
||
"Source" form shall mean the preferred form for making modifications, | ||
including but not limited to software source code, documentation | ||
source, and configuration files. | ||
|
||
"Object" form shall mean any form resulting from mechanical | ||
transformation or translation of a Source form, including but | ||
not limited to compiled object code, generated documentation, | ||
and conversions to other media types. | ||
|
||
"Work" shall mean the work of authorship, whether in Source or | ||
Object form, made available under the License, as indicated by a | ||
copyright notice that is included in or attached to the work | ||
(an example is provided in the Appendix below). | ||
|
||
"Derivative Works" shall mean any work, whether in Source or Object | ||
form, that is based on (or derived from) the Work and for which the | ||
editorial revisions, annotations, elaborations, or other modifications | ||
represent, as a whole, an original work of authorship. For the purposes | ||
of this License, Derivative Works shall not include works that remain | ||
separable from, or merely link (or bind by name) to the interfaces of, | ||
the Work and Derivative Works thereof. | ||
|
||
"Contribution" shall mean any work of authorship, including | ||
the original version of the Work and any modifications or additions | ||
to that Work or Derivative Works thereof, that is intentionally | ||
submitted to Licensor for inclusion in the Work by the copyright owner | ||
or by an individual or Legal Entity authorized to submit on behalf of | ||
the copyright owner. For the purposes of this definition, "submitted" | ||
means any form of electronic, verbal, or written communication sent | ||
to the Licensor or its representatives, including but not limited to | ||
communication on electronic mailing lists, source code control systems, | ||
and issue tracking systems that are managed by, or on behalf of, the | ||
Licensor for the purpose of discussing and improving the Work, but | ||
excluding communication that is conspicuously marked or otherwise | ||
designated in writing by the copyright owner as "Not a Contribution." | ||
|
||
"Contributor" shall mean Licensor and any individual or Legal Entity | ||
on behalf of whom a Contribution has been received by Licensor and | ||
subsequently incorporated within the Work. | ||
|
||
2. Grant of Copyright License. Subject to the terms and conditions of | ||
this License, each Contributor hereby grants to You a perpetual, | ||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable | ||
copyright license to reproduce, prepare Derivative Works of, | ||
publicly display, publicly perform, sublicense, and distribute the | ||
Work and such Derivative Works in Source or Object form. | ||
|
||
3. Grant of Patent License. Subject to the terms and conditions of | ||
this License, each Contributor hereby grants to You a perpetual, | ||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable | ||
(except as stated in this section) patent license to make, have made, | ||
use, offer to sell, sell, import, and otherwise transfer the Work, | ||
where such license applies only to those patent claims licensable | ||
by such Contributor that are necessarily infringed by their | ||
Contribution(s) alone or by combination of their Contribution(s) | ||
with the Work to which such Contribution(s) was submitted. If You | ||
institute patent litigation against any entity (including a | ||
cross-claim or counterclaim in a lawsuit) alleging that the Work | ||
or a Contribution incorporated within the Work constitutes direct | ||
or contributory patent infringement, then any patent licenses | ||
granted to You under this License for that Work shall terminate | ||
as of the date such litigation is filed. | ||
|
||
4. Redistribution. You may reproduce and distribute copies of the | ||
Work or Derivative Works thereof in any medium, with or without | ||
modifications, and in Source or Object form, provided that You | ||
meet the following conditions: | ||
|
||
(a) You must give any other recipients of the Work or | ||
Derivative Works a copy of this License; and | ||
|
||
(b) You must cause any modified files to carry prominent notices | ||
stating that You changed the files; and | ||
|
||
(c) You must retain, in the Source form of any Derivative Works | ||
that You distribute, all copyright, patent, trademark, and | ||
attribution notices from the Source form of the Work, | ||
excluding those notices that do not pertain to any part of | ||
the Derivative Works; and | ||
|
||
(d) If the Work includes a "NOTICE" text file as part of its | ||
distribution, then any Derivative Works that You distribute must | ||
include a readable copy of the attribution notices contained | ||
within such NOTICE file, excluding those notices that do not | ||
pertain to any part of the Derivative Works, in at least one | ||
of the following places: within a NOTICE text file distributed | ||
as part of the Derivative Works; within the Source form or | ||
documentation, if provided along with the Derivative Works; or, | ||
within a display generated by the Derivative Works, if and | ||
wherever such third-party notices normally appear. The contents | ||
of the NOTICE file are for informational purposes only and | ||
do not modify the License. You may add Your own attribution | ||
notices within Derivative Works that You distribute, alongside | ||
or as an addendum to the NOTICE text from the Work, provided | ||
that such additional attribution notices cannot be construed | ||
as modifying the License. | ||
|
||
You may add Your own copyright statement to Your modifications and | ||
may provide additional or different license terms and conditions | ||
for use, reproduction, or distribution of Your modifications, or | ||
for any such Derivative Works as a whole, provided Your use, | ||
reproduction, and distribution of the Work otherwise complies with | ||
the conditions stated in this License. | ||
|
||
5. Submission of Contributions. Unless You explicitly state otherwise, | ||
any Contribution intentionally submitted for inclusion in the Work | ||
by You to the Licensor shall be under the terms and conditions of | ||
this License, without any additional terms or conditions. | ||
Notwithstanding the above, nothing herein shall supersede or modify | ||
the terms of any separate license agreement you may have executed | ||
with Licensor regarding such Contributions. | ||
|
||
6. Trademarks. This License does not grant permission to use the trade | ||
names, trademarks, service marks, or product names of the Licensor, | ||
except as required for reasonable and customary use in describing the | ||
origin of the Work and reproducing the content of the NOTICE file. | ||
|
||
7. Disclaimer of Warranty. Unless required by applicable law or | ||
agreed to in writing, Licensor provides the Work (and each | ||
Contributor provides its Contributions) on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | ||
implied, including, without limitation, any warranties or conditions | ||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A | ||
PARTICULAR PURPOSE. You are solely responsible for determining the | ||
appropriateness of using or redistributing the Work and assume any | ||
risks associated with Your exercise of permissions under this License. | ||
|
||
8. Limitation of Liability. In no event and under no legal theory, | ||
whether in tort (including negligence), contract, or otherwise, | ||
unless required by applicable law (such as deliberate and grossly | ||
negligent acts) or agreed to in writing, shall any Contributor be | ||
liable to You for damages, including any direct, indirect, special, | ||
incidental, or consequential damages of any character arising as a | ||
result of this License or out of the use or inability to use the | ||
Work (including but not limited to damages for loss of goodwill, | ||
work stoppage, computer failure or malfunction, or any and all | ||
other commercial damages or losses), even if such Contributor | ||
has been advised of the possibility of such damages. | ||
|
||
9. Accepting Warranty or Additional Liability. While redistributing | ||
the Work or Derivative Works thereof, You may choose to offer, | ||
and charge a fee for, acceptance of support, warranty, indemnity, | ||
or other liability obligations and/or rights consistent with this | ||
License. However, in accepting such obligations, You may act only | ||
on Your own behalf and on Your sole responsibility, not on behalf | ||
of any other Contributor, and only if You agree to indemnify, | ||
defend, and hold each Contributor harmless for any liability | ||
incurred by, or claims asserted against, such Contributor by reason | ||
of your accepting any such warranty or additional liability. | ||
|
||
END OF TERMS AND CONDITIONS | ||
|
||
APPENDIX: How to apply the Apache License to your work. | ||
|
||
To apply the Apache License to your work, attach the following | ||
boilerplate notice, with the fields enclosed by brackets "[]" | ||
replaced with your own identifying information. (Don't include | ||
the brackets!) The text should be enclosed in the appropriate | ||
comment syntax for the file format. We also recommend that a | ||
file or class name and description of purpose be included on the | ||
same "printed page" as the copyright notice for easier | ||
identification within third-party archives. | ||
|
||
Copyright [yyyy] [name of copyright owner] | ||
|
||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
|
||
http://www.apache.org/licenses/LICENSE-2.0 | ||
|
||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
|
||
|
||
---- LLVM Exceptions to the Apache 2.0 License ---- | ||
|
||
As an exception, if, as a result of your compiling your source code, portions | ||
of this Software are embedded into an Object form of such source code, you | ||
may redistribute such embedded portions in such Object form without complying | ||
with the conditions of Sections 4(a), 4(b) and 4(d) of the License. | ||
|
||
In addition, if you combine or link compiled forms of this Software with | ||
software that is licensed under the GPLv2 ("Combined Software") and if a | ||
court of competent jurisdiction determines that the patent provision (Section | ||
3), the indemnity provision (Section 9) or other Section of the License | ||
conflicts with the conditions of the GPLv2, you may retroactively and | ||
prospectively choose to deem waived or otherwise exclude such Section(s) of | ||
the License, but only in their entirety and only with respect to the Combined | ||
Software. | ||
|
||
============================================================================== | ||
Software from third parties included in the LLVM Project: | ||
============================================================================== | ||
The LLVM Project contains third party software which is under different license | ||
terms. All such code will be identified clearly using at least one of two | ||
mechanisms: | ||
1) It will be in a separate directory tree with its own `LICENSE.txt` or | ||
`LICENSE` file at the top containing the specific license and restrictions | ||
which apply to that software, or | ||
2) It will contain specific license and restriction terms at the top of every | ||
file. | ||
|
||
============================================================================== | ||
Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy): | ||
============================================================================== | ||
University of Illinois/NCSA | ||
Open Source License | ||
|
||
Copyright (c) 2003-2019 University of Illinois at Urbana-Champaign. | ||
All rights reserved. | ||
|
||
Developed by: | ||
|
||
LLVM Team | ||
|
||
University of Illinois at Urbana-Champaign | ||
|
||
http://llvm.org | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy of | ||
this software and associated documentation files (the "Software"), to deal with | ||
the Software without restriction, including without limitation the rights to | ||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies | ||
of the Software, and to permit persons to whom the Software is furnished to do | ||
so, subject to the following conditions: | ||
|
||
* Redistributions of source code must retain the above copyright notice, | ||
this list of conditions and the following disclaimers. | ||
|
||
* Redistributions in binary form must reproduce the above copyright notice, | ||
this list of conditions and the following disclaimers in the | ||
documentation and/or other materials provided with the distribution. | ||
|
||
* Neither the names of the LLVM Team, University of Illinois at | ||
Urbana-Champaign, nor the names of its contributors may be used to | ||
endorse or promote products derived from this Software without specific | ||
prior written permission. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS | ||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# External LLVM | ||
|
||
All files in the `llvm` subfolder are 1:1 copied from LLVM 14.0.6 and are subject to the LLVM license. | ||
You can find a copy of the LLVM license [here](./LLVM-LICENSE.txt). | ||
|
||
Note that we needed to copy these files, as LLVM removed them in the transition from version 14 to 15. | ||
To avoid LLVM from blocking PhASAR releases, we provide these files ourselves as a *temporary solution*. | ||
|
||
We, as the PhASAR development core team, do not aim for maintaining the here provided LLVM code and will not add any modifications to it (bugfixes, enhancements, etc.). | ||
Rather, we will add a custom replacement eventually. |
269 changes: 269 additions & 0 deletions
269
lib/PhasarLLVM/Pointer/external/llvm/AliasAnalysisSummary.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,269 @@ | ||
//=====- CFLSummary.h - Abstract stratified sets implementation. --------=====// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
/// \file | ||
/// This file defines various utility types and functions useful to | ||
/// summary-based alias analysis. | ||
/// | ||
/// Summary-based analysis, also known as bottom-up analysis, is a style of | ||
/// interprocedrual static analysis that tries to analyze the callees before the | ||
/// callers get analyzed. The key idea of summary-based analysis is to first | ||
/// process each function independently, outline its behavior in a condensed | ||
/// summary, and then instantiate the summary at the callsite when the said | ||
/// function is called elsewhere. This is often in contrast to another style | ||
/// called top-down analysis, in which callers are always analyzed first before | ||
/// the callees. | ||
/// | ||
/// In a summary-based analysis, functions must be examined independently and | ||
/// out-of-context. We have no information on the state of the memory, the | ||
/// arguments, the global values, and anything else external to the function. To | ||
/// carry out the analysis conservative assumptions have to be made about those | ||
/// external states. In exchange for the potential loss of precision, the | ||
/// summary we obtain this way is highly reusable, which makes the analysis | ||
/// easier to scale to large programs even if carried out context-sensitively. | ||
/// | ||
/// Currently, all CFL-based alias analyses adopt the summary-based approach | ||
/// and therefore heavily rely on this header. | ||
/// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef LLVM_ANALYSIS_ALIASANALYSISSUMMARY_H | ||
#define LLVM_ANALYSIS_ALIASANALYSISSUMMARY_H | ||
|
||
#include "llvm/ADT/DenseMapInfo.h" | ||
#include "llvm/ADT/Optional.h" | ||
#include "llvm/ADT/SmallVector.h" | ||
|
||
#include <bitset> | ||
|
||
namespace llvm { | ||
|
||
class CallBase; | ||
class Value; | ||
|
||
namespace cflaa { | ||
|
||
//===----------------------------------------------------------------------===// | ||
// AliasAttr related stuffs | ||
//===----------------------------------------------------------------------===// | ||
|
||
/// The number of attributes that AliasAttr should contain. Attributes are | ||
/// described below, and 32 was an arbitrary choice because it fits nicely in 32 | ||
/// bits (because we use a bitset for AliasAttr). | ||
static const unsigned NumAliasAttrs = 32; | ||
|
||
/// These are attributes that an alias analysis can use to mark certain special | ||
/// properties of a given pointer. Refer to the related functions below to see | ||
/// what kinds of attributes are currently defined. | ||
typedef std::bitset<NumAliasAttrs> AliasAttrs; | ||
|
||
/// Attr represent whether the said pointer comes from an unknown source | ||
/// (such as opaque memory or an integer cast). | ||
AliasAttrs getAttrNone(); | ||
|
||
/// AttrUnknown represent whether the said pointer comes from a source not known | ||
/// to alias analyses (such as opaque memory or an integer cast). | ||
AliasAttrs getAttrUnknown(); | ||
bool hasUnknownAttr(AliasAttrs); | ||
|
||
/// AttrCaller represent whether the said pointer comes from a source not known | ||
/// to the current function but known to the caller. Values pointed to by the | ||
/// arguments of the current function have this attribute set | ||
AliasAttrs getAttrCaller(); | ||
bool hasCallerAttr(AliasAttrs); | ||
bool hasUnknownOrCallerAttr(AliasAttrs); | ||
|
||
/// AttrEscaped represent whether the said pointer comes from a known source but | ||
/// escapes to the unknown world (e.g. casted to an integer, or passed as an | ||
/// argument to opaque function). Unlike non-escaped pointers, escaped ones may | ||
/// alias pointers coming from unknown sources. | ||
AliasAttrs getAttrEscaped(); | ||
bool hasEscapedAttr(AliasAttrs); | ||
|
||
/// AttrGlobal represent whether the said pointer is a global value. | ||
/// AttrArg represent whether the said pointer is an argument, and if so, what | ||
/// index the argument has. | ||
AliasAttrs getGlobalOrArgAttrFromValue(const Value &); | ||
bool isGlobalOrArgAttr(AliasAttrs); | ||
|
||
/// Given an AliasAttrs, return a new AliasAttrs that only contains attributes | ||
/// meaningful to the caller. This function is primarily used for | ||
/// interprocedural analysis | ||
/// Currently, externally visible AliasAttrs include AttrUnknown, AttrGlobal, | ||
/// and AttrEscaped | ||
AliasAttrs getExternallyVisibleAttrs(AliasAttrs); | ||
|
||
//===----------------------------------------------------------------------===// | ||
// Function summary related stuffs | ||
//===----------------------------------------------------------------------===// | ||
|
||
/// The maximum number of arguments we can put into a summary. | ||
static const unsigned MaxSupportedArgsInSummary = 50; | ||
|
||
/// We use InterfaceValue to describe parameters/return value, as well as | ||
/// potential memory locations that are pointed to by parameters/return value, | ||
/// of a function. | ||
/// Index is an integer which represents a single parameter or a return value. | ||
/// When the index is 0, it refers to the return value. Non-zero index i refers | ||
/// to the i-th parameter. | ||
/// DerefLevel indicates the number of dereferences one must perform on the | ||
/// parameter/return value to get this InterfaceValue. | ||
struct InterfaceValue { | ||
unsigned Index; | ||
unsigned DerefLevel; | ||
}; | ||
|
||
inline bool operator==(InterfaceValue LHS, InterfaceValue RHS) { | ||
return LHS.Index == RHS.Index && LHS.DerefLevel == RHS.DerefLevel; | ||
} | ||
inline bool operator!=(InterfaceValue LHS, InterfaceValue RHS) { | ||
return !(LHS == RHS); | ||
} | ||
inline bool operator<(InterfaceValue LHS, InterfaceValue RHS) { | ||
return LHS.Index < RHS.Index || | ||
(LHS.Index == RHS.Index && LHS.DerefLevel < RHS.DerefLevel); | ||
} | ||
inline bool operator>(InterfaceValue LHS, InterfaceValue RHS) { | ||
return RHS < LHS; | ||
} | ||
inline bool operator<=(InterfaceValue LHS, InterfaceValue RHS) { | ||
return !(RHS < LHS); | ||
} | ||
inline bool operator>=(InterfaceValue LHS, InterfaceValue RHS) { | ||
return !(LHS < RHS); | ||
} | ||
|
||
// We use UnknownOffset to represent pointer offsets that cannot be determined | ||
// at compile time. Note that MemoryLocation::UnknownSize cannot be used here | ||
// because we require a signed value. | ||
static const int64_t UnknownOffset = INT64_MAX; | ||
|
||
inline int64_t addOffset(int64_t LHS, int64_t RHS) { | ||
if (LHS == UnknownOffset || RHS == UnknownOffset) | ||
return UnknownOffset; | ||
// FIXME: Do we need to guard against integer overflow here? | ||
return LHS + RHS; | ||
} | ||
|
||
/// We use ExternalRelation to describe an externally visible aliasing relations | ||
/// between parameters/return value of a function. | ||
struct ExternalRelation { | ||
InterfaceValue From, To; | ||
int64_t Offset; | ||
}; | ||
|
||
inline bool operator==(ExternalRelation LHS, ExternalRelation RHS) { | ||
return LHS.From == RHS.From && LHS.To == RHS.To && LHS.Offset == RHS.Offset; | ||
} | ||
inline bool operator!=(ExternalRelation LHS, ExternalRelation RHS) { | ||
return !(LHS == RHS); | ||
} | ||
inline bool operator<(ExternalRelation LHS, ExternalRelation RHS) { | ||
if (LHS.From < RHS.From) | ||
return true; | ||
if (LHS.From > RHS.From) | ||
return false; | ||
if (LHS.To < RHS.To) | ||
return true; | ||
if (LHS.To > RHS.To) | ||
return false; | ||
return LHS.Offset < RHS.Offset; | ||
} | ||
inline bool operator>(ExternalRelation LHS, ExternalRelation RHS) { | ||
return RHS < LHS; | ||
} | ||
inline bool operator<=(ExternalRelation LHS, ExternalRelation RHS) { | ||
return !(RHS < LHS); | ||
} | ||
inline bool operator>=(ExternalRelation LHS, ExternalRelation RHS) { | ||
return !(LHS < RHS); | ||
} | ||
|
||
/// We use ExternalAttribute to describe an externally visible AliasAttrs | ||
/// for parameters/return value. | ||
struct ExternalAttribute { | ||
InterfaceValue IValue; | ||
AliasAttrs Attr; | ||
}; | ||
|
||
/// AliasSummary is just a collection of ExternalRelation and ExternalAttribute | ||
struct AliasSummary { | ||
// RetParamRelations is a collection of ExternalRelations. | ||
SmallVector<ExternalRelation, 8> RetParamRelations; | ||
|
||
// RetParamAttributes is a collection of ExternalAttributes. | ||
SmallVector<ExternalAttribute, 8> RetParamAttributes; | ||
}; | ||
|
||
/// This is the result of instantiating InterfaceValue at a particular call | ||
struct InstantiatedValue { | ||
Value *Val; | ||
unsigned DerefLevel; | ||
}; | ||
Optional<InstantiatedValue> instantiateInterfaceValue(InterfaceValue IValue, | ||
CallBase &Call); | ||
|
||
inline bool operator==(InstantiatedValue LHS, InstantiatedValue RHS) { | ||
return LHS.Val == RHS.Val && LHS.DerefLevel == RHS.DerefLevel; | ||
} | ||
inline bool operator!=(InstantiatedValue LHS, InstantiatedValue RHS) { | ||
return !(LHS == RHS); | ||
} | ||
inline bool operator<(InstantiatedValue LHS, InstantiatedValue RHS) { | ||
return std::less<Value *>()(LHS.Val, RHS.Val) || | ||
(LHS.Val == RHS.Val && LHS.DerefLevel < RHS.DerefLevel); | ||
} | ||
inline bool operator>(InstantiatedValue LHS, InstantiatedValue RHS) { | ||
return RHS < LHS; | ||
} | ||
inline bool operator<=(InstantiatedValue LHS, InstantiatedValue RHS) { | ||
return !(RHS < LHS); | ||
} | ||
inline bool operator>=(InstantiatedValue LHS, InstantiatedValue RHS) { | ||
return !(LHS < RHS); | ||
} | ||
|
||
/// This is the result of instantiating ExternalRelation at a particular | ||
/// callsite | ||
struct InstantiatedRelation { | ||
InstantiatedValue From, To; | ||
int64_t Offset; | ||
}; | ||
Optional<InstantiatedRelation> | ||
instantiateExternalRelation(ExternalRelation ERelation, CallBase &Call); | ||
|
||
/// This is the result of instantiating ExternalAttribute at a particular | ||
/// callsite | ||
struct InstantiatedAttr { | ||
InstantiatedValue IValue; | ||
AliasAttrs Attr; | ||
}; | ||
Optional<InstantiatedAttr> instantiateExternalAttribute(ExternalAttribute EAttr, | ||
CallBase &Call); | ||
} // namespace cflaa | ||
|
||
template <> struct DenseMapInfo<cflaa::InstantiatedValue> { | ||
static inline cflaa::InstantiatedValue getEmptyKey() { | ||
return cflaa::InstantiatedValue{DenseMapInfo<Value *>::getEmptyKey(), | ||
DenseMapInfo<unsigned>::getEmptyKey()}; | ||
} | ||
static inline cflaa::InstantiatedValue getTombstoneKey() { | ||
return cflaa::InstantiatedValue{DenseMapInfo<Value *>::getTombstoneKey(), | ||
DenseMapInfo<unsigned>::getTombstoneKey()}; | ||
} | ||
static unsigned getHashValue(const cflaa::InstantiatedValue &IV) { | ||
return DenseMapInfo<std::pair<Value *, unsigned>>::getHashValue( | ||
std::make_pair(IV.Val, IV.DerefLevel)); | ||
} | ||
static bool isEqual(const cflaa::InstantiatedValue &LHS, | ||
const cflaa::InstantiatedValue &RHS) { | ||
return LHS.Val == RHS.Val && LHS.DerefLevel == RHS.DerefLevel; | ||
} | ||
}; | ||
} // namespace llvm | ||
|
||
#endif |
57 changes: 57 additions & 0 deletions
57
lib/PhasarLLVM/Pointer/external/llvm/CFLAliasAnalysisUtils.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
//=- CFLAliasAnalysisUtils.h - Utilities for CFL Alias Analysis ----*- C++-*-=// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// \file | ||
// These are the utilities/helpers used by the CFL Alias Analyses available in | ||
// tree, i.e. Steensgaard's and Andersens'. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef LLVM_ANALYSIS_CFLALIASANALYSISUTILS_H | ||
#define LLVM_ANALYSIS_CFLALIASANALYSISUTILS_H | ||
|
||
#include "llvm/IR/Function.h" | ||
#include "llvm/IR/ValueHandle.h" | ||
|
||
namespace llvm { | ||
namespace cflaa { | ||
|
||
template <typename AAResult> struct FunctionHandle final : public CallbackVH { | ||
FunctionHandle(Function *Fn, AAResult *Result) | ||
: CallbackVH(Fn), Result(Result) { | ||
assert(Fn != nullptr); | ||
assert(Result != nullptr); | ||
} | ||
|
||
void deleted() override { removeSelfFromCache(); } | ||
void allUsesReplacedWith(Value *) override { removeSelfFromCache(); } | ||
|
||
private: | ||
AAResult *Result; | ||
|
||
void removeSelfFromCache() { | ||
assert(Result != nullptr); | ||
auto *Val = getValPtr(); | ||
Result->evict(cast<Function>(Val)); | ||
setValPtr(nullptr); | ||
} | ||
}; | ||
|
||
static inline const Function *parentFunctionOfValue(const Value *Val) { | ||
if (auto *Inst = dyn_cast<Instruction>(Val)) { | ||
auto *Bb = Inst->getParent(); | ||
return Bb->getParent(); | ||
} | ||
|
||
if (auto *Arg = dyn_cast<Argument>(Val)) | ||
return Arg->getParent(); | ||
return nullptr; | ||
} | ||
} // namespace cflaa | ||
} // namespace llvm | ||
|
||
#endif // LLVM_ANALYSIS_CFLALIASANALYSISUTILS_H |
934 changes: 934 additions & 0 deletions
934
lib/PhasarLLVM/Pointer/external/llvm/CFLAndersAliasAnalysis.cpp
Large diffs are not rendered by default.
Oops, something went wrong.
128 changes: 128 additions & 0 deletions
128
lib/PhasarLLVM/Pointer/external/llvm/CFLAndersAliasAnalysis.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
//==- CFLAndersAliasAnalysis.h - Unification-based Alias Analysis -*- C++-*-==// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
/// \file | ||
/// This is the interface for LLVM's inclusion-based alias analysis | ||
/// implemented with CFL graph reachability. | ||
/// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef LLVM_ANALYSIS_CFLANDERSALIASANALYSIS_H | ||
#define LLVM_ANALYSIS_CFLANDERSALIASANALYSIS_H | ||
|
||
#include "llvm/ADT/DenseMap.h" | ||
#include "llvm/ADT/Optional.h" | ||
#include "llvm/Analysis/AliasAnalysis.h" | ||
#include "llvm/Analysis/CFLAliasAnalysisUtils.h" | ||
#include "llvm/IR/PassManager.h" | ||
#include "llvm/Pass.h" | ||
|
||
#include <forward_list> | ||
#include <memory> | ||
|
||
namespace llvm { | ||
|
||
class Function; | ||
class MemoryLocation; | ||
class TargetLibraryInfo; | ||
|
||
namespace cflaa { | ||
|
||
struct AliasSummary; | ||
|
||
} // end namespace cflaa | ||
|
||
class CFLAndersAAResult : public AAResultBase<CFLAndersAAResult> { | ||
friend AAResultBase<CFLAndersAAResult>; | ||
|
||
class FunctionInfo; | ||
|
||
public: | ||
explicit CFLAndersAAResult( | ||
std::function<const TargetLibraryInfo &(Function &F)> GetTLI); | ||
CFLAndersAAResult(CFLAndersAAResult &&RHS); | ||
~CFLAndersAAResult(); | ||
|
||
/// Handle invalidation events from the new pass manager. | ||
/// By definition, this result is stateless and so remains valid. | ||
bool invalidate(Function &, const PreservedAnalyses &, | ||
FunctionAnalysisManager::Invalidator &) { | ||
return false; | ||
} | ||
|
||
/// Evict the given function from cache | ||
void evict(const Function *Fn); | ||
|
||
/// Get the alias summary for the given function | ||
/// Return nullptr if the summary is not found or not available | ||
const cflaa::AliasSummary *getAliasSummary(const Function &); | ||
|
||
AliasResult query(const MemoryLocation &, const MemoryLocation &); | ||
AliasResult alias(const MemoryLocation &, const MemoryLocation &, | ||
AAQueryInfo &); | ||
|
||
private: | ||
/// Ensures that the given function is available in the cache. | ||
/// Returns the appropriate entry from the cache. | ||
const Optional<FunctionInfo> &ensureCached(const Function &); | ||
|
||
/// Inserts the given Function into the cache. | ||
void scan(const Function &); | ||
|
||
/// Build summary for a given function | ||
FunctionInfo buildInfoFrom(const Function &); | ||
|
||
std::function<const TargetLibraryInfo &(Function &F)> GetTLI; | ||
|
||
/// Cached mapping of Functions to their StratifiedSets. | ||
/// If a function's sets are currently being built, it is marked | ||
/// in the cache as an Optional without a value. This way, if we | ||
/// have any kind of recursion, it is discernable from a function | ||
/// that simply has empty sets. | ||
DenseMap<const Function *, Optional<FunctionInfo>> Cache; | ||
|
||
std::forward_list<cflaa::FunctionHandle<CFLAndersAAResult>> Handles; | ||
}; | ||
|
||
/// Analysis pass providing a never-invalidated alias analysis result. | ||
/// | ||
/// FIXME: We really should refactor CFL to use the analysis more heavily, and | ||
/// in particular to leverage invalidation to trigger re-computation. | ||
class CFLAndersAA : public AnalysisInfoMixin<CFLAndersAA> { | ||
friend AnalysisInfoMixin<CFLAndersAA>; | ||
|
||
static AnalysisKey Key; | ||
|
||
public: | ||
using Result = CFLAndersAAResult; | ||
|
||
CFLAndersAAResult run(Function &F, FunctionAnalysisManager &AM); | ||
}; | ||
|
||
/// Legacy wrapper pass to provide the CFLAndersAAResult object. | ||
class CFLAndersAAWrapperPass : public ImmutablePass { | ||
std::unique_ptr<CFLAndersAAResult> Result; | ||
|
||
public: | ||
static char ID; | ||
|
||
CFLAndersAAWrapperPass(); | ||
|
||
CFLAndersAAResult &getResult() { return *Result; } | ||
const CFLAndersAAResult &getResult() const { return *Result; } | ||
|
||
void initializePass() override; | ||
void getAnalysisUsage(AnalysisUsage &AU) const override; | ||
}; | ||
|
||
// createCFLAndersAAWrapperPass - This pass implements a set-based approach to | ||
// alias analysis. | ||
ImmutablePass *createCFLAndersAAWrapperPass(); | ||
|
||
} // end namespace llvm | ||
|
||
#endif // LLVM_ANALYSIS_CFLANDERSALIASANALYSIS_H |
Large diffs are not rendered by default.
Oops, something went wrong.
367 changes: 367 additions & 0 deletions
367
lib/PhasarLLVM/Pointer/external/llvm/CFLSteensAliasAnalysis.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,367 @@ | ||
//===- CFLSteensAliasAnalysis.cpp - Unification-based Alias Analysis ------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// This file implements a CFL-base, summary-based alias analysis algorithm. It | ||
// does not depend on types. The algorithm is a mixture of the one described in | ||
// "Demand-driven alias analysis for C" by Xin Zheng and Radu Rugina, and "Fast | ||
// algorithms for Dyck-CFL-reachability with applications to Alias Analysis" by | ||
// Zhang Q, Lyu M R, Yuan H, and Su Z. -- to summarize the papers, we build a | ||
// graph of the uses of a variable, where each node is a memory location, and | ||
// each edge is an action that happened on that memory location. The "actions" | ||
// can be one of Dereference, Reference, or Assign. The precision of this | ||
// analysis is roughly the same as that of an one level context-sensitive | ||
// Steensgaard's algorithm. | ||
// | ||
// Two variables are considered as aliasing iff you can reach one value's node | ||
// from the other value's node and the language formed by concatenating all of | ||
// the edge labels (actions) conforms to a context-free grammar. | ||
// | ||
// Because this algorithm requires a graph search on each query, we execute the | ||
// algorithm outlined in "Fast algorithms..." (mentioned above) | ||
// in order to transform the graph into sets of variables that may alias in | ||
// ~nlogn time (n = number of variables), which makes queries take constant | ||
// time. | ||
//===----------------------------------------------------------------------===// | ||
|
||
// N.B. AliasAnalysis as a whole is phrased as a FunctionPass at the moment, and | ||
// CFLSteensAA is interprocedural. This is *technically* A Bad Thing, because | ||
// FunctionPasses are only allowed to inspect the Function that they're being | ||
// run on. Realistically, this likely isn't a problem until we allow | ||
// FunctionPasses to run concurrently. | ||
|
||
#include "llvm/Analysis/CFLSteensAliasAnalysis.h" | ||
|
||
#include "llvm/ADT/DenseMap.h" | ||
#include "llvm/ADT/Optional.h" | ||
#include "llvm/ADT/SmallVector.h" | ||
#include "llvm/Analysis/TargetLibraryInfo.h" | ||
#include "llvm/IR/Constants.h" | ||
#include "llvm/IR/Function.h" | ||
#include "llvm/IR/Type.h" | ||
#include "llvm/IR/Value.h" | ||
#include "llvm/InitializePasses.h" | ||
#include "llvm/Pass.h" | ||
#include "llvm/Support/Debug.h" | ||
#include "llvm/Support/raw_ostream.h" | ||
|
||
#include "AliasAnalysisSummary.h" | ||
#include "CFLGraph.h" | ||
#include "StratifiedSets.h" | ||
|
||
#include <algorithm> | ||
#include <cassert> | ||
#include <limits> | ||
#include <memory> | ||
#include <utility> | ||
|
||
using namespace llvm; | ||
using namespace llvm::cflaa; | ||
|
||
#define DEBUG_TYPE "cfl-steens-aa" | ||
|
||
CFLSteensAAResult::CFLSteensAAResult( | ||
std::function<const TargetLibraryInfo &(Function &F)> GetTLI) | ||
: GetTLI(std::move(GetTLI)) {} | ||
CFLSteensAAResult::CFLSteensAAResult(CFLSteensAAResult &&Arg) | ||
: AAResultBase(std::move(Arg)), GetTLI(std::move(Arg.GetTLI)) {} | ||
CFLSteensAAResult::~CFLSteensAAResult() = default; | ||
|
||
/// Information we have about a function and would like to keep around. | ||
class CFLSteensAAResult::FunctionInfo { | ||
StratifiedSets<InstantiatedValue> Sets; | ||
AliasSummary Summary; | ||
|
||
public: | ||
FunctionInfo(Function &Fn, const SmallVectorImpl<Value *> &RetVals, | ||
StratifiedSets<InstantiatedValue> S); | ||
|
||
const StratifiedSets<InstantiatedValue> &getStratifiedSets() const { | ||
return Sets; | ||
} | ||
|
||
const AliasSummary &getAliasSummary() const { return Summary; } | ||
}; | ||
|
||
const StratifiedIndex StratifiedLink::SetSentinel = | ||
std::numeric_limits<StratifiedIndex>::max(); | ||
|
||
//===----------------------------------------------------------------------===// | ||
// Function declarations that require types defined in the namespace above | ||
//===----------------------------------------------------------------------===// | ||
|
||
/// Determines whether it would be pointless to add the given Value to our sets. | ||
static bool canSkipAddingToSets(Value *Val) { | ||
// Constants can share instances, which may falsely unify multiple | ||
// sets, e.g. in | ||
// store i32* null, i32** %ptr1 | ||
// store i32* null, i32** %ptr2 | ||
// clearly ptr1 and ptr2 should not be unified into the same set, so | ||
// we should filter out the (potentially shared) instance to | ||
// i32* null. | ||
if (isa<Constant>(Val)) { | ||
// TODO: Because all of these things are constant, we can determine whether | ||
// the data is *actually* mutable at graph building time. This will probably | ||
// come for free/cheap with offset awareness. | ||
bool CanStoreMutableData = isa<GlobalValue>(Val) || | ||
isa<ConstantExpr>(Val) || | ||
isa<ConstantAggregate>(Val); | ||
return !CanStoreMutableData; | ||
} | ||
|
||
return false; | ||
} | ||
|
||
CFLSteensAAResult::FunctionInfo::FunctionInfo( | ||
Function &Fn, const SmallVectorImpl<Value *> &RetVals, | ||
StratifiedSets<InstantiatedValue> S) | ||
: Sets(std::move(S)) { | ||
// Historically, an arbitrary upper-bound of 50 args was selected. We may want | ||
// to remove this if it doesn't really matter in practice. | ||
if (Fn.arg_size() > MaxSupportedArgsInSummary) | ||
return; | ||
|
||
DenseMap<StratifiedIndex, InterfaceValue> InterfaceMap; | ||
|
||
// Our intention here is to record all InterfaceValues that share the same | ||
// StratifiedIndex in RetParamRelations. For each valid InterfaceValue, we | ||
// have its StratifiedIndex scanned here and check if the index is presented | ||
// in InterfaceMap: if it is not, we add the correspondence to the map; | ||
// otherwise, an aliasing relation is found and we add it to | ||
// RetParamRelations. | ||
|
||
auto AddToRetParamRelations = [&](unsigned InterfaceIndex, | ||
StratifiedIndex SetIndex) { | ||
unsigned Level = 0; | ||
while (true) { | ||
InterfaceValue CurrValue{InterfaceIndex, Level}; | ||
|
||
auto Itr = InterfaceMap.find(SetIndex); | ||
if (Itr != InterfaceMap.end()) { | ||
if (CurrValue != Itr->second) | ||
Summary.RetParamRelations.push_back( | ||
ExternalRelation{CurrValue, Itr->second, UnknownOffset}); | ||
break; | ||
} | ||
|
||
auto &Link = Sets.getLink(SetIndex); | ||
InterfaceMap.insert(std::make_pair(SetIndex, CurrValue)); | ||
auto ExternalAttrs = getExternallyVisibleAttrs(Link.Attrs); | ||
if (ExternalAttrs.any()) | ||
Summary.RetParamAttributes.push_back( | ||
ExternalAttribute{CurrValue, ExternalAttrs}); | ||
|
||
if (!Link.hasBelow()) | ||
break; | ||
|
||
++Level; | ||
SetIndex = Link.Below; | ||
} | ||
}; | ||
|
||
// Populate RetParamRelations for return values | ||
for (auto *RetVal : RetVals) { | ||
assert(RetVal != nullptr); | ||
assert(RetVal->getType()->isPointerTy()); | ||
auto RetInfo = Sets.find(InstantiatedValue{RetVal, 0}); | ||
if (RetInfo.hasValue()) | ||
AddToRetParamRelations(0, RetInfo->Index); | ||
} | ||
|
||
// Populate RetParamRelations for parameters | ||
unsigned I = 0; | ||
for (auto &Param : Fn.args()) { | ||
if (Param.getType()->isPointerTy()) { | ||
auto ParamInfo = Sets.find(InstantiatedValue{&Param, 0}); | ||
if (ParamInfo.hasValue()) | ||
AddToRetParamRelations(I + 1, ParamInfo->Index); | ||
} | ||
++I; | ||
} | ||
} | ||
|
||
// Builds the graph + StratifiedSets for a function. | ||
CFLSteensAAResult::FunctionInfo CFLSteensAAResult::buildSetsFrom(Function *Fn) { | ||
CFLGraphBuilder<CFLSteensAAResult> GraphBuilder(*this, GetTLI(*Fn), *Fn); | ||
StratifiedSetsBuilder<InstantiatedValue> SetBuilder; | ||
|
||
// Add all CFLGraph nodes and all Dereference edges to StratifiedSets | ||
auto &Graph = GraphBuilder.getCFLGraph(); | ||
for (const auto &Mapping : Graph.value_mappings()) { | ||
auto Val = Mapping.first; | ||
if (canSkipAddingToSets(Val)) | ||
continue; | ||
auto &ValueInfo = Mapping.second; | ||
|
||
assert(ValueInfo.getNumLevels() > 0); | ||
SetBuilder.add(InstantiatedValue{Val, 0}); | ||
SetBuilder.noteAttributes(InstantiatedValue{Val, 0}, | ||
ValueInfo.getNodeInfoAtLevel(0).Attr); | ||
for (unsigned I = 0, E = ValueInfo.getNumLevels() - 1; I < E; ++I) { | ||
SetBuilder.add(InstantiatedValue{Val, I + 1}); | ||
SetBuilder.noteAttributes(InstantiatedValue{Val, I + 1}, | ||
ValueInfo.getNodeInfoAtLevel(I + 1).Attr); | ||
SetBuilder.addBelow(InstantiatedValue{Val, I}, | ||
InstantiatedValue{Val, I + 1}); | ||
} | ||
} | ||
|
||
// Add all assign edges to StratifiedSets | ||
for (const auto &Mapping : Graph.value_mappings()) { | ||
auto Val = Mapping.first; | ||
if (canSkipAddingToSets(Val)) | ||
continue; | ||
auto &ValueInfo = Mapping.second; | ||
|
||
for (unsigned I = 0, E = ValueInfo.getNumLevels(); I < E; ++I) { | ||
auto Src = InstantiatedValue{Val, I}; | ||
for (auto &Edge : ValueInfo.getNodeInfoAtLevel(I).Edges) | ||
SetBuilder.addWith(Src, Edge.Other); | ||
} | ||
} | ||
|
||
return FunctionInfo(*Fn, GraphBuilder.getReturnValues(), SetBuilder.build()); | ||
} | ||
|
||
void CFLSteensAAResult::scan(Function *Fn) { | ||
auto InsertPair = Cache.insert(std::make_pair(Fn, Optional<FunctionInfo>())); | ||
(void)InsertPair; | ||
assert(InsertPair.second && | ||
"Trying to scan a function that has already been cached"); | ||
|
||
// Note that we can't do Cache[Fn] = buildSetsFrom(Fn) here: the function call | ||
// may get evaluated after operator[], potentially triggering a DenseMap | ||
// resize and invalidating the reference returned by operator[] | ||
auto FunInfo = buildSetsFrom(Fn); | ||
Cache[Fn] = std::move(FunInfo); | ||
|
||
Handles.emplace_front(Fn, this); | ||
} | ||
|
||
void CFLSteensAAResult::evict(Function *Fn) { Cache.erase(Fn); } | ||
|
||
/// Ensures that the given function is available in the cache, and returns the | ||
/// entry. | ||
const Optional<CFLSteensAAResult::FunctionInfo> & | ||
CFLSteensAAResult::ensureCached(Function *Fn) { | ||
auto Iter = Cache.find(Fn); | ||
if (Iter == Cache.end()) { | ||
scan(Fn); | ||
Iter = Cache.find(Fn); | ||
assert(Iter != Cache.end()); | ||
assert(Iter->second.hasValue()); | ||
} | ||
return Iter->second; | ||
} | ||
|
||
const AliasSummary *CFLSteensAAResult::getAliasSummary(Function &Fn) { | ||
auto &FunInfo = ensureCached(&Fn); | ||
if (FunInfo.hasValue()) | ||
return &FunInfo->getAliasSummary(); | ||
else | ||
return nullptr; | ||
} | ||
|
||
AliasResult CFLSteensAAResult::query(const MemoryLocation &LocA, | ||
const MemoryLocation &LocB) { | ||
auto *ValA = const_cast<Value *>(LocA.Ptr); | ||
auto *ValB = const_cast<Value *>(LocB.Ptr); | ||
|
||
if (!ValA->getType()->isPointerTy() || !ValB->getType()->isPointerTy()) | ||
return AliasResult::NoAlias; | ||
|
||
Function *Fn = nullptr; | ||
Function *MaybeFnA = const_cast<Function *>(parentFunctionOfValue(ValA)); | ||
Function *MaybeFnB = const_cast<Function *>(parentFunctionOfValue(ValB)); | ||
if (!MaybeFnA && !MaybeFnB) { | ||
// The only times this is known to happen are when globals + InlineAsm are | ||
// involved | ||
LLVM_DEBUG( | ||
dbgs() | ||
<< "CFLSteensAA: could not extract parent function information.\n"); | ||
return AliasResult::MayAlias; | ||
} | ||
|
||
if (MaybeFnA) { | ||
Fn = MaybeFnA; | ||
assert((!MaybeFnB || MaybeFnB == MaybeFnA) && | ||
"Interprocedural queries not supported"); | ||
} else { | ||
Fn = MaybeFnB; | ||
} | ||
|
||
assert(Fn != nullptr); | ||
auto &MaybeInfo = ensureCached(Fn); | ||
assert(MaybeInfo.hasValue()); | ||
|
||
auto &Sets = MaybeInfo->getStratifiedSets(); | ||
auto MaybeA = Sets.find(InstantiatedValue{ValA, 0}); | ||
if (!MaybeA.hasValue()) | ||
return AliasResult::MayAlias; | ||
|
||
auto MaybeB = Sets.find(InstantiatedValue{ValB, 0}); | ||
if (!MaybeB.hasValue()) | ||
return AliasResult::MayAlias; | ||
|
||
auto SetA = *MaybeA; | ||
auto SetB = *MaybeB; | ||
auto AttrsA = Sets.getLink(SetA.Index).Attrs; | ||
auto AttrsB = Sets.getLink(SetB.Index).Attrs; | ||
|
||
// If both values are local (meaning the corresponding set has attribute | ||
// AttrNone or AttrEscaped), then we know that CFLSteensAA fully models them: | ||
// they may-alias each other if and only if they are in the same set. | ||
// If at least one value is non-local (meaning it either is global/argument or | ||
// it comes from unknown sources like integer cast), the situation becomes a | ||
// bit more interesting. We follow three general rules described below: | ||
// - Non-local values may alias each other | ||
// - AttrNone values do not alias any non-local values | ||
// - AttrEscaped do not alias globals/arguments, but they may alias | ||
// AttrUnknown values | ||
if (SetA.Index == SetB.Index) | ||
return AliasResult::MayAlias; | ||
if (AttrsA.none() || AttrsB.none()) | ||
return AliasResult::NoAlias; | ||
if (hasUnknownOrCallerAttr(AttrsA) || hasUnknownOrCallerAttr(AttrsB)) | ||
return AliasResult::MayAlias; | ||
if (isGlobalOrArgAttr(AttrsA) && isGlobalOrArgAttr(AttrsB)) | ||
return AliasResult::MayAlias; | ||
return AliasResult::NoAlias; | ||
} | ||
|
||
AnalysisKey CFLSteensAA::Key; | ||
|
||
CFLSteensAAResult CFLSteensAA::run(Function &F, FunctionAnalysisManager &AM) { | ||
auto GetTLI = [&AM](Function &F) -> const TargetLibraryInfo & { | ||
return AM.getResult<TargetLibraryAnalysis>(F); | ||
}; | ||
return CFLSteensAAResult(GetTLI); | ||
} | ||
|
||
char CFLSteensAAWrapperPass::ID = 0; | ||
INITIALIZE_PASS(CFLSteensAAWrapperPass, "cfl-steens-aa", | ||
"Unification-Based CFL Alias Analysis", false, true) | ||
|
||
ImmutablePass *llvm::createCFLSteensAAWrapperPass() { | ||
return new CFLSteensAAWrapperPass(); | ||
} | ||
|
||
CFLSteensAAWrapperPass::CFLSteensAAWrapperPass() : ImmutablePass(ID) { | ||
initializeCFLSteensAAWrapperPassPass(*PassRegistry::getPassRegistry()); | ||
} | ||
|
||
void CFLSteensAAWrapperPass::initializePass() { | ||
auto GetTLI = [this](Function &F) -> const TargetLibraryInfo & { | ||
return this->getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F); | ||
}; | ||
Result.reset(new CFLSteensAAResult(GetTLI)); | ||
} | ||
|
||
void CFLSteensAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const { | ||
AU.setPreservesAll(); | ||
AU.addRequired<TargetLibraryInfoWrapperPass>(); | ||
} |
145 changes: 145 additions & 0 deletions
145
lib/PhasarLLVM/Pointer/external/llvm/CFLSteensAliasAnalysis.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
//==- CFLSteensAliasAnalysis.h - Unification-based Alias Analysis -*- C++-*-==// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
/// \file | ||
/// This is the interface for LLVM's unification-based alias analysis | ||
/// implemented with CFL graph reachability. | ||
/// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef LLVM_ANALYSIS_CFLSTEENSALIASANALYSIS_H | ||
#define LLVM_ANALYSIS_CFLSTEENSALIASANALYSIS_H | ||
|
||
#include "llvm/ADT/DenseMap.h" | ||
#include "llvm/ADT/Optional.h" | ||
#include "llvm/Analysis/AliasAnalysis.h" | ||
#include "llvm/Analysis/CFLAliasAnalysisUtils.h" | ||
#include "llvm/Analysis/MemoryLocation.h" | ||
#include "llvm/IR/PassManager.h" | ||
#include "llvm/Pass.h" | ||
#include "llvm/Support/Casting.h" | ||
|
||
#include <forward_list> | ||
#include <memory> | ||
|
||
namespace llvm { | ||
|
||
class Function; | ||
class TargetLibraryInfo; | ||
|
||
namespace cflaa { | ||
|
||
struct AliasSummary; | ||
|
||
} // end namespace cflaa | ||
|
||
class CFLSteensAAResult : public AAResultBase<CFLSteensAAResult> { | ||
friend AAResultBase<CFLSteensAAResult>; | ||
|
||
class FunctionInfo; | ||
|
||
public: | ||
explicit CFLSteensAAResult( | ||
std::function<const TargetLibraryInfo &(Function &)> GetTLI); | ||
CFLSteensAAResult(CFLSteensAAResult &&Arg); | ||
~CFLSteensAAResult(); | ||
|
||
/// Handle invalidation events from the new pass manager. | ||
/// | ||
/// By definition, this result is stateless and so remains valid. | ||
bool invalidate(Function &, const PreservedAnalyses &, | ||
FunctionAnalysisManager::Invalidator &) { | ||
return false; | ||
} | ||
|
||
/// Inserts the given Function into the cache. | ||
void scan(Function *Fn); | ||
|
||
void evict(Function *Fn); | ||
|
||
/// Ensures that the given function is available in the cache. | ||
/// Returns the appropriate entry from the cache. | ||
const Optional<FunctionInfo> &ensureCached(Function *Fn); | ||
|
||
/// Get the alias summary for the given function | ||
/// Return nullptr if the summary is not found or not available | ||
const cflaa::AliasSummary *getAliasSummary(Function &Fn); | ||
|
||
AliasResult query(const MemoryLocation &LocA, const MemoryLocation &LocB); | ||
|
||
AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB, | ||
AAQueryInfo &AAQI) { | ||
if (LocA.Ptr == LocB.Ptr) | ||
return AliasResult::MustAlias; | ||
|
||
// Comparisons between global variables and other constants should be | ||
// handled by BasicAA. | ||
// CFLSteensAA may report NoAlias when comparing a GlobalValue and | ||
// ConstantExpr, but every query needs to have at least one Value tied to a | ||
// Function, and neither GlobalValues nor ConstantExprs are. | ||
if (isa<Constant>(LocA.Ptr) && isa<Constant>(LocB.Ptr)) | ||
return AAResultBase::alias(LocA, LocB, AAQI); | ||
|
||
AliasResult QueryResult = query(LocA, LocB); | ||
if (QueryResult == AliasResult::MayAlias) | ||
return AAResultBase::alias(LocA, LocB, AAQI); | ||
|
||
return QueryResult; | ||
} | ||
|
||
private: | ||
std::function<const TargetLibraryInfo &(Function &)> GetTLI; | ||
|
||
/// Cached mapping of Functions to their StratifiedSets. | ||
/// If a function's sets are currently being built, it is marked | ||
/// in the cache as an Optional without a value. This way, if we | ||
/// have any kind of recursion, it is discernable from a function | ||
/// that simply has empty sets. | ||
DenseMap<Function *, Optional<FunctionInfo>> Cache; | ||
std::forward_list<cflaa::FunctionHandle<CFLSteensAAResult>> Handles; | ||
|
||
FunctionInfo buildSetsFrom(Function *F); | ||
}; | ||
|
||
/// Analysis pass providing a never-invalidated alias analysis result. | ||
/// | ||
/// FIXME: We really should refactor CFL to use the analysis more heavily, and | ||
/// in particular to leverage invalidation to trigger re-computation of sets. | ||
class CFLSteensAA : public AnalysisInfoMixin<CFLSteensAA> { | ||
friend AnalysisInfoMixin<CFLSteensAA>; | ||
|
||
static AnalysisKey Key; | ||
|
||
public: | ||
using Result = CFLSteensAAResult; | ||
|
||
CFLSteensAAResult run(Function &F, FunctionAnalysisManager &AM); | ||
}; | ||
|
||
/// Legacy wrapper pass to provide the CFLSteensAAResult object. | ||
class CFLSteensAAWrapperPass : public ImmutablePass { | ||
std::unique_ptr<CFLSteensAAResult> Result; | ||
|
||
public: | ||
static char ID; | ||
|
||
CFLSteensAAWrapperPass(); | ||
|
||
CFLSteensAAResult &getResult() { return *Result; } | ||
const CFLSteensAAResult &getResult() const { return *Result; } | ||
|
||
void initializePass() override; | ||
void getAnalysisUsage(AnalysisUsage &AU) const override; | ||
}; | ||
|
||
// createCFLSteensAAWrapperPass - This pass implements a set-based approach to | ||
// alias analysis. | ||
ImmutablePass *createCFLSteensAAWrapperPass(); | ||
|
||
} // end namespace llvm | ||
|
||
#endif // LLVM_ANALYSIS_CFLSTEENSALIASANALYSIS_H |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters