From 177deb45aad8c0459e7c8c50ffadb972261f07c6 Mon Sep 17 00:00:00 2001 From: Robert Widmann Date: Wed, 14 Aug 2019 11:36:34 -0700 Subject: [PATCH 1/5] Add a renamed hint to a deprecation warning --- Sources/LLVM/FunctionType.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/LLVM/FunctionType.swift b/Sources/LLVM/FunctionType.swift index 32a44012..6524f422 100644 --- a/Sources/LLVM/FunctionType.swift +++ b/Sources/LLVM/FunctionType.swift @@ -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 From a5825aee1c23dd7d7107fc7e57e6fb5021a680fd Mon Sep 17 00:00:00 2001 From: Robert Widmann Date: Wed, 14 Aug 2019 11:36:52 -0700 Subject: [PATCH 2/5] Improve docs for noalias and tailcall --- Sources/LLVM/Call.swift | 6 ++++-- Sources/LLVM/Function+Attributes.swift | 8 ++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Sources/LLVM/Call.swift b/Sources/LLVM/Call.swift index aa729901..dd9c7fd9 100644 --- a/Sources/LLVM/Call.swift +++ b/Sources/LLVM/Call.swift @@ -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 { diff --git a/Sources/LLVM/Function+Attributes.swift b/Sources/LLVM/Function+Attributes.swift index 10aa59a5..9ea922fa 100644 --- a/Sources/LLVM/Function+Attributes.swift +++ b/Sources/LLVM/Function+Attributes.swift @@ -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. From 431838a2aa52956548abd56fac390b70d2e076ed Mon Sep 17 00:00:00 2001 From: Robert Widmann Date: Wed, 14 Aug 2019 11:56:46 -0700 Subject: [PATCH 3/5] Add Global AA pass --- Sources/LLVM/PassManager.swift | 6 ++++++ Sources/LLVM/PassPipeliner.swift | 2 ++ Sources/llvmshims/include/shim.h | 2 ++ Sources/llvmshims/src/shim.cpp | 7 +++++++ 4 files changed, 17 insertions(+) diff --git a/Sources/LLVM/PassManager.swift b/Sources/LLVM/PassManager.swift index 7d30cf2d..0eb3b546 100644 --- a/Sources/LLVM/PassManager.swift +++ b/Sources/LLVM/PassManager.swift @@ -141,6 +141,12 @@ public enum Pass { case scopedNoAliasAA /// LLVM's primary stateless and local alias analysis. 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. diff --git a/Sources/LLVM/PassPipeliner.swift b/Sources/LLVM/PassPipeliner.swift index 5039f7df..d87e5e90 100644 --- a/Sources/LLVM/PassPipeliner.swift +++ b/Sources/LLVM/PassPipeliner.swift @@ -321,6 +321,8 @@ extension PassPipeliner { LLVMAddScopedNoAliasAAPass(passManager) case .basicAliasAnalysis: LLVMAddBasicAliasAnalysisPass(passManager) + case .globalsAliasAnalysis: + LLVMAddGlobalsAAWrapperPass(passManager) case .unifyFunctionExitNodes: LLVMAddUnifyFunctionExitNodesPass(passManager) case .alwaysInliner: diff --git a/Sources/llvmshims/include/shim.h b/Sources/llvmshims/include/shim.h index 8ba8522b..9767e95f 100644 --- a/Sources/llvmshims/include/shim.h +++ b/Sources/llvmshims/include/shim.h @@ -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 *)); diff --git a/Sources/llvmshims/src/shim.cpp b/Sources/llvmshims/src/shim.cpp index 6716d576..f33a59c2 100644 --- a/Sources/llvmshims/src/shim.cpp +++ b/Sources/llvmshims/src/shim.cpp @@ -127,6 +127,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, @@ -377,3 +380,7 @@ void LLVMAddInternalizePassWithMustPreservePredicate( return Pred(wrap(&GV), Context) == 0 ? false : true; })); } + +void LLVMAddGlobalsAAWrapperPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createGlobalsAAWrapperPass()); +} From a1113b1d88ee0140186116af2541cf97b87067a6 Mon Sep 17 00:00:00 2001 From: Robert Widmann Date: Wed, 14 Aug 2019 11:57:33 -0700 Subject: [PATCH 4/5] Improve AA docs Better describe TBAA tree systems and the broad mechanisms behind a few different alias analysis passes and how they differ. --- Sources/LLVM/MDBuilder.swift | 59 +++++++++++++++++++++++++++++----- Sources/LLVM/PassManager.swift | 26 ++++++++++++++- 2 files changed, 76 insertions(+), 9 deletions(-) diff --git a/Sources/LLVM/MDBuilder.swift b/Sources/LLVM/MDBuilder.swift index 3a9ac360..2298404a 100644 --- a/Sources/LLVM/MDBuilder.swift +++ b/Sources/LLVM/MDBuilder.swift @@ -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. @@ -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 diff --git a/Sources/LLVM/PassManager.swift b/Sources/LLVM/PassManager.swift index 0eb3b546..f37e60df 100644 --- a/Sources/LLVM/PassManager.swift +++ b/Sources/LLVM/PassManager.swift @@ -134,12 +134,36 @@ 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. From 54241485260c07571eea9da899281e902eeabfb0 Mon Sep 17 00:00:00 2001 From: Robert Widmann Date: Wed, 14 Aug 2019 12:23:01 -0700 Subject: [PATCH 5/5] Shuffle headers --- Sources/llvmshims/src/shim.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Sources/llvmshims/src/shim.cpp b/Sources/llvmshims/src/shim.cpp index f33a59c2..85cb156e 100644 --- a/Sources/llvmshims/src/shim.cpp +++ b/Sources/llvmshims/src/shim.cpp @@ -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"