Skip to content

Improve Some Alias Analysis Infrastructure #212

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Aug 14, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions Sources/LLVM/Call.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@ public struct Call: IRInstruction {
set { LLVMSetInstructionCallConv(self.llvm, newValue.llvm.rawValue) }
}

/// Returns whether this function call is a tail call. That is, if the callee
/// may reuse the stack memory of the caller.
/// Returns whether this function call is a tail call.
///
/// A tail call may not reference memory in the stack frame of the calling
/// function. Therefore, the callee may reuse the stack memory of the caller.
///
/// This attribute requires support from the target architecture.
public var isTailCall: Bool {
Expand Down
8 changes: 8 additions & 0 deletions Sources/LLVM/Function+Attributes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,14 @@ public enum AttributeKind: String {
/// argument or return value are not also accessed, during the execution of
/// the function, via pointer values not based on the argument or return
/// value.
///
/// The `noalias` attribute may appear in one of two location: on arguments
/// types or on return types. On argument types, `noalias` acts like the
/// `restrict` keyword in C and C++ and implies that no other pointer value
/// points to this object. On return types, `noalias` implies that the
/// returned pointer is not aliased by any other pointer in the program.
///
/// Practically, this allows LLVM to reorder accesses to this memory.
case noalias
/// This indicates that the callee does not make any copies of the pointer
/// that outlive the callee itself.
Expand Down
2 changes: 1 addition & 1 deletion Sources/LLVM/FunctionType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public struct FunctionType: IRType {
/// - parameter isVarArg: Indicates whether this function type is variadic.
/// Defaults to `false`.
/// - note: The context of this type is taken from it's `returnType`
@available(*, deprecated, message: "Use the more concise initializer instead")
@available(*, deprecated, message: "Use the more concise initializer instead", renamed: "FunctionType.init(_:_:variadic:)")
public init(argTypes: [IRType], returnType: IRType, isVarArg: Bool = false) {
self.parameterTypes = argTypes
self.returnType = returnType
Expand Down
59 changes: 51 additions & 8 deletions Sources/LLVM/MDBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,12 @@ public struct TBAAStructField {
}

extension MDBuilder {
/// Build a metadata node for the root of a TBAA hierarchy with the given name.
/// Build a metadata node for the root of a TBAA hierarchy with the given
/// name.
///
/// The root node of a TBAA hierarchy describes a boundary for a source
/// language's type system. For the purposes of optimization, a TBAA analysis
/// pass must consider ancestors of two different root systems `mayalias`.
///
/// - Parameters:
/// - name: The name of the TBAA root node.
Expand Down Expand Up @@ -306,13 +311,51 @@ extension MDBuilder {
/// Builds a TBAA Type Descriptor.
///
/// Type descriptors describe the type system of the higher level language
/// being compiled. Scalar type descriptors describe types that do not
/// contain other types. Each scalar type has a parent type, which must also
/// be a scalar type or the TBAA root. Via this parent relation, scalar types
/// within a TBAA root form a tree. Struct type descriptors denote types that
/// contain a sequence of other type descriptors, at known offsets. These
/// contained type descriptors can either be struct type descriptors
/// themselves or scalar type descriptors.
/// being compiled and come in two variants:
///
/// Scalar Type Descriptors
/// =======================
///
/// Scalar type descriptors describe types that do not contain other types,
/// such as fixed-width integral and floating-point types. A scalar type
/// has a single parent, which is required to be another scalar type or
/// the TBAA root node. For example, in C, `int32_t` would be described be
/// a scalar type node with a parent pointer to `unsigned char` which, in
/// turn, points to the root for C.
///
/// ```
/// +----------+ +------+ +-----------+
/// | | | | | |
/// | uint32_t +---> char +---> TBAA Root |
/// | | | | | |
/// +----------+ +------+ +-----------+
/// ```
///
/// Struct Type Descriptors
/// =======================
///
/// Struct type descriptors describe types that contain a sequence of other
/// type descriptors, at known offsets, as fields. These field type
/// descriptors can either be struct type descriptors themselves or scalar
/// type descriptors.
///
/// ```
/// +----------+
/// | |
/// +-------> uint32_t +----+
/// | | | |
/// | +----------+ |
/// +------------+ +---v--+ +-----------+
/// | | | | | |
/// | SomeStruct | | char +---> TBAA Root |
/// | | | | | |
/// +------------+ +---^--+ +-----------+
/// | +-------+ |
/// | | | |
/// +----------> float +----+
/// | |
/// +-------+
/// ```
///
/// - Parameters:
/// - parent: The parent type node of this type node or the TBAA root node
Expand Down
32 changes: 31 additions & 1 deletion Sources/LLVM/PassManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -134,13 +134,43 @@ public enum Pass {
case earlyCSE
/// Removes `llvm.expect` intrinsics and creates "block_weights" metadata.
case lowerExpectIntrinsic
/// Adds metadata to LLVM IR types and performs metadata-based TBAA.
/// Adds metadata to LLVM IR types and performs metadata-based
/// Type-Based Alias Analysis (TBAA).
///
/// TBAA requires that two pointers to objects of different types must never
/// alias. Because memory in LLVM is typeless, TBAA is performed using
/// special metadata nodes describing aliasing relationships between types
/// in the source language(s).
///
/// To construct this metadata, see `MDBuilder`.
case typeBasedAliasAnalysis
/// Adds metadata to LLVM IR types and performs metadata-based scoped no-alias
/// analysis.
case scopedNoAliasAA
/// LLVM's primary stateless and local alias analysis.
///
/// Given a pointer value, walk the use-def chain to find out how that
/// pointer is used. The traversal terminates at global variables and
/// aliases, stack allocations, and values of non-pointer types - referred
/// to as "underlying objects". Analysis may reach multiple underlying object
/// values because of branching control flow. If the set of underlying
/// objects for one pointer has a non-empty intersection with another, those
/// two pointers are deemed `mayalias`. Else, an empty intersection deems
/// those pointers `noalias`.
///
/// Basic Alias Analysis should generally be scheduled ahead of other
/// AA passes. This is because it is more conservative than other passes
/// about declaring two pointers `mustalias`, and does so fairly efficiently.
/// For example, loads through two members of a union with distinct types are
/// declared by TBAA to be `noalias`, where BasicAA considers them
/// `mustalias`.
case basicAliasAnalysis
/// Performs alias and mod/ref analysis for internal global values that
/// do not have their address taken.
///
/// Internal global variables that are only loaded from may be marked as
/// constants.
case globalsAliasAnalysis
/// This pass is used to ensure that functions have at most one return
/// instruction in them. Additionally, it keeps track of which node is
/// the new exit node of the CFG.
Expand Down
2 changes: 2 additions & 0 deletions Sources/LLVM/PassPipeliner.swift
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,8 @@ extension PassPipeliner {
LLVMAddScopedNoAliasAAPass(passManager)
case .basicAliasAnalysis:
LLVMAddBasicAliasAnalysisPass(passManager)
case .globalsAliasAnalysis:
LLVMAddGlobalsAAWrapperPass(passManager)
case .unifyFunctionExitNodes:
LLVMAddUnifyFunctionExitNodesPass(passManager)
case .alwaysInliner:
Expand Down
2 changes: 2 additions & 0 deletions Sources/llvmshims/include/shim.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ void LLVMAppendExistingBasicBlock(LLVMValueRef Fn,

void LLVMAddAddDiscriminatorsPass(LLVMPassManagerRef PM);

void LLVMAddGlobalsAAWrapperPass(LLVMPassManagerRef PM);

void LLVMAddInternalizePassWithMustPreservePredicate(
LLVMPassManagerRef PM, void *Context,
LLVMBool (*MustPreserve)(LLVMValueRef, void *));
Expand Down
14 changes: 11 additions & 3 deletions Sources/llvmshims/src/shim.cpp
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
#include "llvm-c/Core.h"
#include "llvm-c/Object.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Analysis/GlobalsModRef.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DIBuilder.h"
#include "llvm-c/Core.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/Support/ARMTargetParser.h"
#include "llvm/Object/MachOUniversal.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/ARMTargetParser.h"
#include "llvm/Transforms/Utils.h"
#include "llvm/Transforms/IPO.h"

Expand Down Expand Up @@ -127,6 +128,9 @@ extern "C" {
// https://reviews.llvm.org/D58624
void LLVMAddAddDiscriminatorsPass(LLVMPassManagerRef PM);

// https://reviews.llvm.org/D66237
void LLVMAddGlobalsAAWrapperPass(LLVMPassManagerRef PM);

// https://reviews.llvm.org/D62456
void LLVMAddInternalizePassWithMustPreservePredicate(
LLVMPassManagerRef PM, void *Context,
Expand Down Expand Up @@ -377,3 +381,7 @@ void LLVMAddInternalizePassWithMustPreservePredicate(
return Pred(wrap(&GV), Context) == 0 ? false : true;
}));
}

void LLVMAddGlobalsAAWrapperPass(LLVMPassManagerRef PM) {
unwrap(PM)->add(createGlobalsAAWrapperPass());
}