From 4fc432b464f378f4f2cb7e7303eeb551f10b4cc0 Mon Sep 17 00:00:00 2001 From: Andrey Yao Date: Mon, 28 Mar 2022 17:44:40 -0400 Subject: [PATCH 01/11] Blog post TBAA intro --- content/blog/2022-03-22-type-alias/index.html | 42 +++++++++++++++++++ .../blog/2022-03-22-type-alias/index.html~ | 42 +++++++++++++++++++ content/blog/2022-03-22-type-alias/index.md | 24 +++++++++++ content/blog/2022-03-22-type-alias/index.md~ | 0 4 files changed, 108 insertions(+) create mode 100644 content/blog/2022-03-22-type-alias/index.html create mode 100644 content/blog/2022-03-22-type-alias/index.html~ create mode 100644 content/blog/2022-03-22-type-alias/index.md create mode 100644 content/blog/2022-03-22-type-alias/index.md~ diff --git a/content/blog/2022-03-22-type-alias/index.html b/content/blog/2022-03-22-type-alias/index.html new file mode 100644 index 000000000..c0bccecc4 --- /dev/null +++ b/content/blog/2022-03-22-type-alias/index.html @@ -0,0 +1,42 @@ + + + + + + +index.html + + + + + + +

+++ +title = “Type-based Alias Analysis” +[extra] +latex = true +[[extra.authors]] +name = “Andrew Butt” +link = “TODO” +[[extra.authors]] +name = “Andrey Yao” +link = “https://www.youtube.com/watch?v=dQw4w9WgXcQ” ++++

+ +

Introduction

+ +

The type system of a statically-typed language allows compilers to reject illegal programs during the type-checking stage of compilation. In a sense, the typing information attached to variables, functions, etc. is a refinement on the set of valid program states, which can be approximated without ever running the program. Although programming language types are often used to locate certain errors during compile time, it’s not their only use.

+ +

“Type-Based Alias Analysis” by Diwan, McKinley, and Moss examines how the same principal can be applied to alias analysis, a type of conservative analysis that determines whether two given pointer variables might interfere with each other, i.e. pointing to the same memory address. Although there had been prior research on alias analysis, Diwan et al.’s type-based alias analysis (TBAA) has the following advantages: +* It is flow-insensitive and runs on linear time, as opposed to many other alias analyses which are expensive to compute. +* It performs almost equally well under an open world assumption as it does in closed world. It’s compatible with the principle of modular programming.

+ +

They also presented evaluations of TBAA. They performed static and dynamic performance analyses on the effectiveness of TBAA when used for redundant load elimination (RLE). Perhaps most notably, they adopted the strategy of limit analysis by comparing empirical speedups with the maximum possible speedups.

+ +

In this blog post, we will first study the specific ideas of TBAA with examples in Java-like syntax, as opposed to Modula-3, the language used in the paper. Then we will review the performance analyses and discuss potential factors behind the empirical results. We will then digress a little bit and talk about extensions to TBAA for more complicated programming language features. Finally we will briefly touch upon the general philosophy of empirical evaluations.

+ +

Type System Preliminaries

+ + + diff --git a/content/blog/2022-03-22-type-alias/index.html~ b/content/blog/2022-03-22-type-alias/index.html~ new file mode 100644 index 000000000..f5e30397f --- /dev/null +++ b/content/blog/2022-03-22-type-alias/index.html~ @@ -0,0 +1,42 @@ + + + + + + +index.html + + + + + + +

+++ +title = “Type-based Alias Analysis” +[extra] +latex = true +[[extra.authors]] +name = “Andrew Butt” +link = “TODO” +[[extra.authors]] +name = “Andrey Yao” +link = “https://www.youtube.com/watch?v=dQw4w9WgXcQ” ++++

+ +

Introduction

+ +

The type system of a statically-typed language allows compilers to reject illegal programs during the type-checking stage of compilation. In a sense, the typing information attached to variables, functions, etc. is a refinement on the set of valid program states, which can be approximated without ever running the program. Although programming language types are often used to locate certain errors during compile time, it’s not their only use.

+ +

“Type-Based Alias Analysis” by Diwan, McKinley, and Moss examines how the same principal can be applied to alias analysis, a type of conservative analysis that determines whether two given pointer variables might interfere with each other, i.e. pointing to the same memory address. Although there had been prior research on alias analysis, Diwan et al.’s type-based alias analysis (TBAA) has the following advantages: +* It is flow-insensitive and runs on linear time, as opposed to many other alias analyses which are expensive to compute. +* It performs almost equally well under an open world assumption as it does in closed world. It’s compatible with the principle of modular programming.

+ +

They also presented evaluations of TBAA. They performed static and dynamic performance analyses on the effectiveness of TBAA when used for redundant load elimination (RLE). Perhaps most notably, they adopted the strategy of limit analysis by comparing empirical speedups with the maximum possible speedups.

+ +

In this blog post, we will first study the specific ideas of TBAA with examples in Java-like syntax, as opposed to Modula-3, the language used in the paper. Then we will review the performance analyses and discuss potential factors behind the empirical results. We will then digress a little bit and talk about extensions to TBAA for more complicated programming language features. Finally we will briefly touch upon the general philosophy of empirical evaluations.

+ +

Type System Preliminaries.

+ + + diff --git a/content/blog/2022-03-22-type-alias/index.md b/content/blog/2022-03-22-type-alias/index.md new file mode 100644 index 000000000..91271685a --- /dev/null +++ b/content/blog/2022-03-22-type-alias/index.md @@ -0,0 +1,24 @@ ++++ +title = "Type-based Alias Analysis" +[extra] +latex = true +[[extra.authors]] +name = "Andrew Butt" +link = "TODO" +[[extra.authors]] +name = "Andrey Yao" +link = "https://www.youtube.com/watch?v=dQw4w9WgXcQ" ++++ + +### Introduction +The type system of a statically-typed language allows compilers to reject illegal programs during the type-checking stage of compilation. In a sense, the typing information attached to variables, functions, etc. is a refinement on the set of valid program states, which can be approximated without ever running the program. Although programming language types are often used to locate certain errors during compile time, it's not their only use. + +"Type-Based Alias Analysis" by Diwan, McKinley, and Moss examines how the same principal can be applied to alias analysis, a type of conservative analysis that determines whether two given pointer variables might interfere with each other, i.e. pointing to the same memory address. Although there had been prior research on alias analysis, Diwan et al.'s type-based alias analysis (TBAA) has the following advantages: +* It is flow-insensitive and runs on linear time, as opposed to many other alias analyses which are expensive to compute. +* It performs almost equally well under an open world assumption as it does in closed world. It's compatible with the principle of modular programming. + +They also presented evaluations of TBAA. They performed static and dynamic performance analyses on the effectiveness of TBAA when used for redundant load elimination (RLE). Perhaps most notably, they adopted the strategy of limit analysis by comparing empirical speedups with the maximum possible speedups. + +In this blog post, we will first study the specific ideas of TBAA with examples in Java-like syntax, as opposed to Modula-3, the language used in the paper. Then we will review the performance analyses and discuss potential factors behind the empirical results. We will then digress a little bit and talk about extensions to TBAA for more complicated programming language features. Finally we will briefly touch upon the general philosophy of empirical evaluations. + +### Type System Preliminaries diff --git a/content/blog/2022-03-22-type-alias/index.md~ b/content/blog/2022-03-22-type-alias/index.md~ new file mode 100644 index 000000000..e69de29bb From 6839e7360c83b33049719468f2193b09809e7177 Mon Sep 17 00:00:00 2001 From: Andrey Yao Date: Mon, 28 Mar 2022 18:38:58 -0400 Subject: [PATCH 02/11] Blog post TBAA section 3 --- content/blog/2022-03-22-type-alias/index.md | 26 ++++++++++++++++-- .../2022-03-22-type-alias/numeric_tower.png | Bin 0 -> 38977 bytes 2 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 content/blog/2022-03-22-type-alias/numeric_tower.png diff --git a/content/blog/2022-03-22-type-alias/index.md b/content/blog/2022-03-22-type-alias/index.md index 91271685a..08421d51d 100644 --- a/content/blog/2022-03-22-type-alias/index.md +++ b/content/blog/2022-03-22-type-alias/index.md @@ -10,7 +10,7 @@ name = "Andrey Yao" link = "https://www.youtube.com/watch?v=dQw4w9WgXcQ" +++ -### Introduction +## Introduction The type system of a statically-typed language allows compilers to reject illegal programs during the type-checking stage of compilation. In a sense, the typing information attached to variables, functions, etc. is a refinement on the set of valid program states, which can be approximated without ever running the program. Although programming language types are often used to locate certain errors during compile time, it's not their only use. "Type-Based Alias Analysis" by Diwan, McKinley, and Moss examines how the same principal can be applied to alias analysis, a type of conservative analysis that determines whether two given pointer variables might interfere with each other, i.e. pointing to the same memory address. Although there had been prior research on alias analysis, Diwan et al.'s type-based alias analysis (TBAA) has the following advantages: @@ -21,4 +21,26 @@ They also presented evaluations of TBAA. They performed static and dynamic perfo In this blog post, we will first study the specific ideas of TBAA with examples in Java-like syntax, as opposed to Modula-3, the language used in the paper. Then we will review the performance analyses and discuss potential factors behind the empirical results. We will then digress a little bit and talk about extensions to TBAA for more complicated programming language features. Finally we will briefly touch upon the general philosophy of empirical evaluations. -### Type System Preliminaries +## Type Preliminaries +** Readers can skip this section if they are already familiar with type systems or wish to focus on TBAA ** + +Given two types $\tau_1$ and $\tau_2$, we say that $\tau_1$ is a subtype of $\tau_2$ if whenever a value of $\tau_2$ is expected, it is legal to supply a value of $\tau_1$ in its place. If we view types as sets and all possible values of a type as its elements, the subtyping relation can be considered roughly the subset relation. Familiar examples from Java include `class Person extends Object` `class LinkedList implements Iterable`, etc. There's also the numeric tower from Typed Racket: +

+alt_text +

+**St-Amour, Vincent et al. “Typing the Numeric Tower.” PADL (2012).** +TODO add this citation to the end + +The subtyping relation is reflexive and transitive. It is an example of a "preorder". We will denote $\tau_1\leq \tau_2$ if the former is a subtype of the latter. There are various ways to construct new subtyping relations given existing ones. For example, if we know that $\tau_1\leq \tau_2$ and $\sigma_1\leq \sigma_2$, it could be reasonable to conclude that the arrow(function) types have $\tau_2\to\sigma_1\leq \tau_1\to\sigma_2$. In this case we say the function type is *covariant* in its return type and *contravariant* in its argument type. + +There are other typing rules for constructs like tuples, records, generics, etc., but we will not list all of them here. However, the select examples above already give us a glimpse into the richness of information encoded by types. In general, in a statically-typed type-safe language, stricter typing rules allows more fine-grained TBAA, which we will see shortly. + +## Type-Based Alias Analysis +TODO introduce access paths + +### Type Declarations Only + +### With Field Access + +### Extended With Assignments + diff --git a/content/blog/2022-03-22-type-alias/numeric_tower.png b/content/blog/2022-03-22-type-alias/numeric_tower.png new file mode 100644 index 0000000000000000000000000000000000000000..915967da29e6981866fa5b5434ad189ed782f0a2 GIT binary patch literal 38977 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 C`9Yij literal 0 HcmV?d00001 From 4ebdd44dcc4d30648a0feb75649852fef5f1605d Mon Sep 17 00:00:00 2001 From: Andrey Yao Date: Tue, 29 Mar 2022 00:08:02 -0400 Subject: [PATCH 03/11] Type Decl TBAA blog post --- content/blog/2022-03-22-type-alias/index.md | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/content/blog/2022-03-22-type-alias/index.md b/content/blog/2022-03-22-type-alias/index.md index 08421d51d..4e20cc815 100644 --- a/content/blog/2022-03-22-type-alias/index.md +++ b/content/blog/2022-03-22-type-alias/index.md @@ -19,12 +19,12 @@ The type system of a statically-typed language allows compilers to reject illega They also presented evaluations of TBAA. They performed static and dynamic performance analyses on the effectiveness of TBAA when used for redundant load elimination (RLE). Perhaps most notably, they adopted the strategy of limit analysis by comparing empirical speedups with the maximum possible speedups. -In this blog post, we will first study the specific ideas of TBAA with examples in Java-like syntax, as opposed to Modula-3, the language used in the paper. Then we will review the performance analyses and discuss potential factors behind the empirical results. We will then digress a little bit and talk about extensions to TBAA for more complicated programming language features. Finally we will briefly touch upon the general philosophy of empirical evaluations. +In this blog post, we will first study the specific ideas of TBAA with examples in C#-like syntax, as opposed to Modula-3, the language used in the paper. Then we will review the performance analyses and discuss potential factors behind the empirical results. We will then digress a little bit and talk about extensions to TBAA for more complicated programming language features. Finally we will briefly touch upon the general philosophy of empirical evaluations. ## Type Preliminaries ** Readers can skip this section if they are already familiar with type systems or wish to focus on TBAA ** -Given two types $\tau_1$ and $\tau_2$, we say that $\tau_1$ is a subtype of $\tau_2$ if whenever a value of $\tau_2$ is expected, it is legal to supply a value of $\tau_1$ in its place. If we view types as sets and all possible values of a type as its elements, the subtyping relation can be considered roughly the subset relation. Familiar examples from Java include `class Person extends Object` `class LinkedList implements Iterable`, etc. There's also the numeric tower from Typed Racket: +Given two types $\tau_1$ and $\tau_2$, we say that $\tau_1$ is a subtype of $\tau_2$ if whenever a value of $\tau_2$ is expected, it is legal to supply a value of $\tau_1$ in its place. If we view types as sets and all possible values of a type as its elements, the subtyping relation can be considered roughly the subset relation. Familiar examples from Java include `class Person extends Object` and `class LinkedList implements Iterable`, etc. There's also the numeric tower from Typed Racket:

alt_text

@@ -36,10 +36,18 @@ The subtyping relation is reflexive and transitive. It is an example of a "preor There are other typing rules for constructs like tuples, records, generics, etc., but we will not list all of them here. However, the select examples above already give us a glimpse into the richness of information encoded by types. In general, in a statically-typed type-safe language, stricter typing rules allows more fine-grained TBAA, which we will see shortly. ## Type-Based Alias Analysis -TODO introduce access paths +TBAA operates on the program AST instead of the IR. Thus, it has access to higher level information than some other program analyses. Let's assume the language we're working with has the following kinds of memory references: + +1. `a.x` Class field access +2. `a[n]` Array indexing +3. `*a` Pointer indirection + +An access path is defined to be any combination of one or more of these memory references. For instance, `(*(a.b).c[3])[2][*d[*e.f]]` is a pathological example of an access path. Basically, access paths are succinct representations of chains of memory references in the AST. We will also define typeof ($\mathcal{P}$) to be the type of the path $\mathcal{P}$. ### Type Declarations Only +To predict whether two paths $\mathcal{P}_1, \mathcal{P}_2$ might alias, an obvious heuristic is to say this is when the (typeof $\mathcal{P}$) has nonempty intersection with the subtypes of (typeof $\mathcal{P}$). Of course, if the two types are disjoint, then if any expression involving $\mathcal{P}_1$ type checks, the same expression with $\mathcal{P}_2$ substituted in place cannot type check, and so the two paths cannot possibly alias. + ### With Field Access ### Extended With Assignments From 1925b39e3fed0026fc153bfc5a3ff897e83c91f8 Mon Sep 17 00:00:00 2001 From: Andrey Yao Date: Tue, 29 Mar 2022 14:06:31 -0400 Subject: [PATCH 04/11] FTD TBAA blog --- content/blog/2022-03-22-type-alias/index.md | 62 ++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/content/blog/2022-03-22-type-alias/index.md b/content/blog/2022-03-22-type-alias/index.md index 4e20cc815..f81ab6473 100644 --- a/content/blog/2022-03-22-type-alias/index.md +++ b/content/blog/2022-03-22-type-alias/index.md @@ -46,9 +46,69 @@ An access path is defined to be any combination of one or more of these memory r ### Type Declarations Only -To predict whether two paths $\mathcal{P}_1, \mathcal{P}_2$ might alias, an obvious heuristic is to say this is when the (typeof $\mathcal{P}$) has nonempty intersection with the subtypes of (typeof $\mathcal{P}$). Of course, if the two types are disjoint, then if any expression involving $\mathcal{P}_1$ type checks, the same expression with $\mathcal{P}_2$ substituted in place cannot type check, and so the two paths cannot possibly alias. +To predict whether two paths $\mathcal{P}_1, \mathcal{P}_2$ might alias, an obvious heuristic is to say this is when the (typeof $\mathcal{P}$) has nonempty intersection with the subtypes of (typeof $\mathcal{P}$). Of course, if the two types are disjoint, then if any expression involving $\mathcal{P}_1$ type checks, the same expression with $\mathcal{P}_2$ substituted in place cannot type check, and so the two paths cannot possibly alias. We will define a function TD, which takes two access paths and returns true iff their types have a common subtype. ### With Field Access +We can extend the above heuristic by taking into account the language fact that `a.f` and `a.g` cannot alias each other for some object `a`. Here we also assume that a field access and an array indexing never alias. This is probably true for many OOP languages. We can summarize whether two access paths may alias inductively using the following table: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
$\mathcal{P}_1$$\mathcal{P}_2$FTD($\mathcal{P}_1$, $\mathcal{P}_2$)
pptrue
p.fq.gf=g $\land$ TD(p,q)
p.f*qAT(p.f) $\land$ TD(p.f, *q)
*pq[m]AT(q[m]) $\land$ TD(*p, q[m])
p.fq[m]false
p[n]q[m]FTD(p, q)
pqTD(p, q)
+ +Here $AT$ stands for "address taken", and AT(\mathcal{P}) is defined to betrue iff the program has ever taken the address of $\mathcal{P}$. One hidden assumption about the table is that the cases are supposed to be checked from top to bottom. For example, if two paths fit case 2 then case 7 on the last row will not apply. Thus it should be very straightforward to implement the function FTD on an AST recursively using ML-style pattern matching. + ### Extended With Assignments From e1c5b0a98c9741006d8faa0ce9622d6ddd322a6d Mon Sep 17 00:00:00 2001 From: Andrey Yao Date: Tue, 29 Mar 2022 20:33:17 -0400 Subject: [PATCH 05/11] Blog TBAA section done --- content/blog/2022-03-22-type-alias/index.md | 32 ++++++++++++++++++--- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/content/blog/2022-03-22-type-alias/index.md b/content/blog/2022-03-22-type-alias/index.md index f81ab6473..b66f5ae4a 100644 --- a/content/blog/2022-03-22-type-alias/index.md +++ b/content/blog/2022-03-22-type-alias/index.md @@ -49,7 +49,7 @@ An access path is defined to be any combination of one or more of these memory r To predict whether two paths $\mathcal{P}_1, \mathcal{P}_2$ might alias, an obvious heuristic is to say this is when the (typeof $\mathcal{P}$) has nonempty intersection with the subtypes of (typeof $\mathcal{P}$). Of course, if the two types are disjoint, then if any expression involving $\mathcal{P}_1$ type checks, the same expression with $\mathcal{P}_2$ substituted in place cannot type check, and so the two paths cannot possibly alias. We will define a function TD, which takes two access paths and returns true iff their types have a common subtype. ### With Field Access -We can extend the above heuristic by taking into account the language fact that `a.f` and `a.g` cannot alias each other for some object `a`. Here we also assume that a field access and an array indexing never alias. This is probably true for many OOP languages. We can summarize whether two access paths may alias inductively using the following table: +We can extend the above heuristic by taking into account the language fact that `a.f` and `a.g` cannot alias each other for some object `a`. Here we also assume that a field access and an array indexing never alias. This is probably true for many OOP languages. We can summarize whether two access paths may alias inductively using the following table, where "FTD" is true iff its arguments paths may alias. - + - + - + - - - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + +
$\mathcal{P}_1$$\mathcal{P}_1$ $\mathcal{P}_2$FTD($\mathcal{P}_1$, $\mathcal{P}_2$)$\tt FTD(\mathcal{P}_1, \mathcal{P}_2)$
pptrue$\tt p$$\tt p$$\tt true$
p.fq.gf=g $\land$ TD(p,q)$\tt p.f$$\tt q.g$$\tt f=g \land TD (p,\,q)$
p.f*qAT(p.f) $\land$ TD(p.f, *q)$\tt p.f$$\tt *q$$\tt AT(p.f) \land TD(p.f,\,*q)$
*pq[m]AT(q[m]) $\land$ TD(*p, q[m])$\tt *p$$\tt q[m]$$\tt AT(q[m]) \land TD(*p,\,q[m])$
p.fq[m]false$\tt p.f$$\tt q[m]$$\tt false$
p[n]q[m]FTD(p, q)$\tt p[n]$$\tt q[m]$$\tt FTD(p,\,q)$
pqTD(p, q)$\tt p$$\tt q$$\tt TD(p,\,q)$
-Here $AT$ stands for "address taken", and AT($\mathcal{P}$) is defined to betrue iff the program has ever taken the address of $\mathcal{P}$. One hidden assumption about the table is that the cases are supposed to be checked from top to bottom. For example, if two paths fit case 2 then case 7 on the last row will not apply. Thus it should be very straightforward to implement the function FTD on an AST recursively using ML-style pattern matching, for example. + +Here $\tt AT$ stands for "address taken", and $\tt AT(\mathcal{P})$ is defined to be true iff the program has ever taken the address of $\mathcal{P}$. One hidden assumption about the table is that the cases are supposed to be checked from top to bottom. For example, if two paths fit case 2 then case 7 on the last row will not apply. Thus it should be very straightforward to implement the function $\tt FTD$ on an AST recursively using ML-style pattern matching, for example. ### Extended With Assignments -So far TD and FTD operate on the assumption that access paths with compatible types and appropriate field accesses can always read or write to each other. However, this can be improved by observing that given $\tau_1\leq\tau_2$, if there are no assignments from variables of type $\tau_1$ to references of type $\tau_2$ anywhere in the program, then references to type $\tau_1$ cannot possibly alias references to type $\tau_2$. This gives rise to the following algorithm: +So far $\tt TD$ and $\tt FTD$ operate on the assumption that access paths with compatible types and appropriate field accesses can always read or write to each other. However, this can be improved by observing that given $\tau_1\leq\tau_2$, if there are no assignments from variables of type $\tau_1$ to references of type $\tau_2$ anywhere in the program, then references to type $\tau_1$ cannot possibly alias references to type $\tau_2$. This gives rise to the following algorithm: ``` [Part 1] @@ -144,7 +140,7 @@ Static evaluation is the most straightforward analysis method. In the case of TB

-From static evaluation we can see that the simplest version of TBAA, TypeDecl, performs significantly worse than the other versions of TBAA. TypeDecl conservatively says that many more reference pairs may alias. However, simple static evaluation does not give the full picture of the benefits of this algorithm. +From static evaluation we can see that the simplest version of TBAA, TypeDecl ($\tt TD$), performs significantly worse than the other versions of TBAA. TypeDecl conservatively says that many more reference pairs may alias. However, simple static evaluation does not give the full picture of the benefits of this algorithm. ### Dynamic Evaluation @@ -152,7 +148,7 @@ In contrast to static evaluation, dynamic evaluation compares the performance of

-As can be seen from the table above, FieldTypeDevl and SMFieldTypeRefs can significantly improve the number of redundant loads removed during optimization, compared to TypeDecl. However, the improvement in the number of redundant loads eliminated depends on the specific benchmark and is not nearly as big of an improvement as static metrics might suggest. Therefore, the paper concludes that a more precise alias analysis is not necessarily much better for real optimization. Additionally, static metrics are insufficient by themselves for evaluation alias analyses. +As can be seen from the table above, FieldTypeDecl ($\tt FTD$) and SMFieldTypeRefs can significantly improve the number of redundant loads removed during optimization, compared to TypeDecl. However, the improvement in the number of redundant loads eliminated depends on the specific benchmark and is not nearly as big of an improvement as static metrics might suggest. Therefore, the paper concludes that a more precise alias analysis is not necessarily much better for real optimization. Additionally, static metrics are insufficient by themselves for evaluation alias analyses. ### Limit Analysis