Skip to content

Commit d63112e

Browse files
authored
Merge pull request #212 from CodaFi/cringeworthy-punning
Improve Some Alias Analysis Infrastructure
2 parents d41cc23 + 5424148 commit d63112e

File tree

8 files changed

+110
-15
lines changed

8 files changed

+110
-15
lines changed

Sources/LLVM/Call.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@ public struct Call: IRInstruction {
2222
set { LLVMSetInstructionCallConv(self.llvm, newValue.llvm.rawValue) }
2323
}
2424

25-
/// Returns whether this function call is a tail call. That is, if the callee
26-
/// may reuse the stack memory of the caller.
25+
/// Returns whether this function call is a tail call.
26+
///
27+
/// A tail call may not reference memory in the stack frame of the calling
28+
/// function. Therefore, the callee may reuse the stack memory of the caller.
2729
///
2830
/// This attribute requires support from the target architecture.
2931
public var isTailCall: Bool {

Sources/LLVM/Function+Attributes.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,14 @@ public enum AttributeKind: String {
163163
/// argument or return value are not also accessed, during the execution of
164164
/// the function, via pointer values not based on the argument or return
165165
/// value.
166+
///
167+
/// The `noalias` attribute may appear in one of two location: on arguments
168+
/// types or on return types. On argument types, `noalias` acts like the
169+
/// `restrict` keyword in C and C++ and implies that no other pointer value
170+
/// points to this object. On return types, `noalias` implies that the
171+
/// returned pointer is not aliased by any other pointer in the program.
172+
///
173+
/// Practically, this allows LLVM to reorder accesses to this memory.
166174
case noalias
167175
/// This indicates that the callee does not make any copies of the pointer
168176
/// that outlive the callee itself.

Sources/LLVM/FunctionType.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public struct FunctionType: IRType {
2121
/// - parameter isVarArg: Indicates whether this function type is variadic.
2222
/// Defaults to `false`.
2323
/// - note: The context of this type is taken from it's `returnType`
24-
@available(*, deprecated, message: "Use the more concise initializer instead")
24+
@available(*, deprecated, message: "Use the more concise initializer instead", renamed: "FunctionType.init(_:_:variadic:)")
2525
public init(argTypes: [IRType], returnType: IRType, isVarArg: Bool = false) {
2626
self.parameterTypes = argTypes
2727
self.returnType = returnType

Sources/LLVM/MDBuilder.swift

Lines changed: 51 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,12 @@ public struct TBAAStructField {
234234
}
235235

236236
extension MDBuilder {
237-
/// Build a metadata node for the root of a TBAA hierarchy with the given name.
237+
/// Build a metadata node for the root of a TBAA hierarchy with the given
238+
/// name.
239+
///
240+
/// The root node of a TBAA hierarchy describes a boundary for a source
241+
/// language's type system. For the purposes of optimization, a TBAA analysis
242+
/// pass must consider ancestors of two different root systems `mayalias`.
238243
///
239244
/// - Parameters:
240245
/// - name: The name of the TBAA root node.
@@ -306,13 +311,51 @@ extension MDBuilder {
306311
/// Builds a TBAA Type Descriptor.
307312
///
308313
/// Type descriptors describe the type system of the higher level language
309-
/// being compiled. Scalar type descriptors describe types that do not
310-
/// contain other types. Each scalar type has a parent type, which must also
311-
/// be a scalar type or the TBAA root. Via this parent relation, scalar types
312-
/// within a TBAA root form a tree. Struct type descriptors denote types that
313-
/// contain a sequence of other type descriptors, at known offsets. These
314-
/// contained type descriptors can either be struct type descriptors
315-
/// themselves or scalar type descriptors.
314+
/// being compiled and come in two variants:
315+
///
316+
/// Scalar Type Descriptors
317+
/// =======================
318+
///
319+
/// Scalar type descriptors describe types that do not contain other types,
320+
/// such as fixed-width integral and floating-point types. A scalar type
321+
/// has a single parent, which is required to be another scalar type or
322+
/// the TBAA root node. For example, in C, `int32_t` would be described be
323+
/// a scalar type node with a parent pointer to `unsigned char` which, in
324+
/// turn, points to the root for C.
325+
///
326+
/// ```
327+
/// +----------+ +------+ +-----------+
328+
/// | | | | | |
329+
/// | uint32_t +---> char +---> TBAA Root |
330+
/// | | | | | |
331+
/// +----------+ +------+ +-----------+
332+
/// ```
333+
///
334+
/// Struct Type Descriptors
335+
/// =======================
336+
///
337+
/// Struct type descriptors describe types that contain a sequence of other
338+
/// type descriptors, at known offsets, as fields. These field type
339+
/// descriptors can either be struct type descriptors themselves or scalar
340+
/// type descriptors.
341+
///
342+
/// ```
343+
/// +----------+
344+
/// | |
345+
/// +-------> uint32_t +----+
346+
/// | | | |
347+
/// | +----------+ |
348+
/// +------------+ +---v--+ +-----------+
349+
/// | | | | | |
350+
/// | SomeStruct | | char +---> TBAA Root |
351+
/// | | | | | |
352+
/// +------------+ +---^--+ +-----------+
353+
/// | +-------+ |
354+
/// | | | |
355+
/// +----------> float +----+
356+
/// | |
357+
/// +-------+
358+
/// ```
316359
///
317360
/// - Parameters:
318361
/// - parent: The parent type node of this type node or the TBAA root node

Sources/LLVM/PassManager.swift

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,13 +134,43 @@ public enum Pass {
134134
case earlyCSE
135135
/// Removes `llvm.expect` intrinsics and creates "block_weights" metadata.
136136
case lowerExpectIntrinsic
137-
/// Adds metadata to LLVM IR types and performs metadata-based TBAA.
137+
/// Adds metadata to LLVM IR types and performs metadata-based
138+
/// Type-Based Alias Analysis (TBAA).
139+
///
140+
/// TBAA requires that two pointers to objects of different types must never
141+
/// alias. Because memory in LLVM is typeless, TBAA is performed using
142+
/// special metadata nodes describing aliasing relationships between types
143+
/// in the source language(s).
144+
///
145+
/// To construct this metadata, see `MDBuilder`.
138146
case typeBasedAliasAnalysis
139147
/// Adds metadata to LLVM IR types and performs metadata-based scoped no-alias
140148
/// analysis.
141149
case scopedNoAliasAA
142150
/// LLVM's primary stateless and local alias analysis.
151+
///
152+
/// Given a pointer value, walk the use-def chain to find out how that
153+
/// pointer is used. The traversal terminates at global variables and
154+
/// aliases, stack allocations, and values of non-pointer types - referred
155+
/// to as "underlying objects". Analysis may reach multiple underlying object
156+
/// values because of branching control flow. If the set of underlying
157+
/// objects for one pointer has a non-empty intersection with another, those
158+
/// two pointers are deemed `mayalias`. Else, an empty intersection deems
159+
/// those pointers `noalias`.
160+
///
161+
/// Basic Alias Analysis should generally be scheduled ahead of other
162+
/// AA passes. This is because it is more conservative than other passes
163+
/// about declaring two pointers `mustalias`, and does so fairly efficiently.
164+
/// For example, loads through two members of a union with distinct types are
165+
/// declared by TBAA to be `noalias`, where BasicAA considers them
166+
/// `mustalias`.
143167
case basicAliasAnalysis
168+
/// Performs alias and mod/ref analysis for internal global values that
169+
/// do not have their address taken.
170+
///
171+
/// Internal global variables that are only loaded from may be marked as
172+
/// constants.
173+
case globalsAliasAnalysis
144174
/// This pass is used to ensure that functions have at most one return
145175
/// instruction in them. Additionally, it keeps track of which node is
146176
/// the new exit node of the CFG.

Sources/LLVM/PassPipeliner.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,8 @@ extension PassPipeliner {
321321
LLVMAddScopedNoAliasAAPass(passManager)
322322
case .basicAliasAnalysis:
323323
LLVMAddBasicAliasAnalysisPass(passManager)
324+
case .globalsAliasAnalysis:
325+
LLVMAddGlobalsAAWrapperPass(passManager)
324326
case .unifyFunctionExitNodes:
325327
LLVMAddUnifyFunctionExitNodesPass(passManager)
326328
case .alwaysInliner:

Sources/llvmshims/include/shim.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ void LLVMAppendExistingBasicBlock(LLVMValueRef Fn,
9898

9999
void LLVMAddAddDiscriminatorsPass(LLVMPassManagerRef PM);
100100

101+
void LLVMAddGlobalsAAWrapperPass(LLVMPassManagerRef PM);
102+
101103
void LLVMAddInternalizePassWithMustPreservePredicate(
102104
LLVMPassManagerRef PM, void *Context,
103105
LLVMBool (*MustPreserve)(LLVMValueRef, void *));

Sources/llvmshims/src/shim.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
1+
#include "llvm-c/Core.h"
12
#include "llvm-c/Object.h"
3+
#include "llvm/ADT/SmallVector.h"
4+
#include "llvm/Analysis/GlobalsModRef.h"
25
#include "llvm/IR/DebugInfo.h"
36
#include "llvm/IR/DIBuilder.h"
4-
#include "llvm-c/Core.h"
57
#include "llvm/IR/Intrinsics.h"
68
#include "llvm/IR/Function.h"
79
#include "llvm/IR/IRBuilder.h"
810
#include "llvm/IR/LegacyPassManager.h"
9-
#include "llvm/Support/ARMTargetParser.h"
1011
#include "llvm/Object/MachOUniversal.h"
1112
#include "llvm/Object/ObjectFile.h"
12-
#include "llvm/ADT/SmallVector.h"
13+
#include "llvm/Support/ARMTargetParser.h"
1314
#include "llvm/Transforms/Utils.h"
1415
#include "llvm/Transforms/IPO.h"
1516

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

131+
// https://reviews.llvm.org/D66237
132+
void LLVMAddGlobalsAAWrapperPass(LLVMPassManagerRef PM);
133+
130134
// https://reviews.llvm.org/D62456
131135
void LLVMAddInternalizePassWithMustPreservePredicate(
132136
LLVMPassManagerRef PM, void *Context,
@@ -377,3 +381,7 @@ void LLVMAddInternalizePassWithMustPreservePredicate(
377381
return Pred(wrap(&GV), Context) == 0 ? false : true;
378382
}));
379383
}
384+
385+
void LLVMAddGlobalsAAWrapperPass(LLVMPassManagerRef PM) {
386+
unwrap(PM)->add(createGlobalsAAWrapperPass());
387+
}

0 commit comments

Comments
 (0)