195 lines
5.5 KiB
Typst
195 lines
5.5 KiB
Typst
// cSpell:ignore fancyuulm uulm
|
|
#import "fancyuulm.typ": fancyuulm, slide, centered-slide, title-slide, config-info, pause, utils
|
|
#import "@preview/codly:1.3.0": codly-init, codly
|
|
|
|
#show: codly-init.with()
|
|
#codly(zebra-fill: none, display-icon: false, display-name: false, stroke: none, radius: 0mm, inset: 0.3em)
|
|
|
|
#show: fancyuulm.with(
|
|
config-info(
|
|
title: [Dataflow Analysis for Compiler Optimization],
|
|
subtitle: [Institute of Software Engineering and Programming Languages],
|
|
author: [Matthias Veigel],
|
|
date: datetime(year: 2025, month: 7, day: 23),
|
|
institution: [University Ulm],
|
|
institute-logo: "logos/sp.svg",
|
|
university-logo: "logos/uulm.svg"
|
|
)
|
|
)
|
|
|
|
#show figure.caption: it => { v(5mm); it.body }
|
|
|
|
#title-slide[
|
|
Dataflow Analysis for Compiler Optimization
|
|
]
|
|
// Hi
|
|
// Will talk about the background, method, results
|
|
|
|
= Background
|
|
#slide[
|
|
#set list(spacing: 1.5em)
|
|
- Looks how data flows through the program during execution
|
|
- Either performed forward or backward
|
|
- Forward looks how data is used by later execution
|
|
- Backward looks what data is still used at a point
|
|
- Performed either on source or immediate representation
|
|
- Used for optimizations, warnings, correctness analysis
|
|
]
|
|
#v(0mm, weak: true)
|
|
#figure( // ssa_form_example
|
|
caption: [C code and respective control flow graph in SSA form, adapted from Fig. 1 in the work of Reissmann, Meyer and Soffa],
|
|
kind: "raw",
|
|
supplement: "",
|
|
grid(
|
|
columns: (1fr, 1.25fr),
|
|
```C
|
|
int x = 2 * 2 + 4;
|
|
x = x - 2;
|
|
if (x < 4)
|
|
x = 10;
|
|
else
|
|
x = 12;
|
|
int y = x * 2;
|
|
```,
|
|
image("ssa-example.svg", height: 16em)
|
|
)
|
|
)
|
|
// what is it
|
|
// where is it used
|
|
// works based on what
|
|
// LLVM
|
|
// Talk about how used in JIT
|
|
|
|
= Methodology
|
|
- RQ1 -- What are the advantages and disadvantages of using dataflow analysis for compiler optimization?
|
|
#pause
|
|
- RQ2 -- How is dataflow analysis used in current compilers?
|
|
#pause
|
|
#v(1em)
|
|
- Total inspected publications: 571
|
|
- Publications included: 15
|
|
- Publications ranging from 1973 to 2024
|
|
- Use a multitude of languages, $1/3$ use LLVM IR
|
|
- Most focused research areas:
|
|
- Algorithms and techniques
|
|
- Analysis speed improvement
|
|
- Custom IR for analysis
|
|
|
|
= Analysis performance
|
|
#slide[
|
|
#set list(spacing: 1.25em)
|
|
- Except for JIT, DFA is done at compile-time
|
|
- Parallelization approaches include: per SSA-node, per function
|
|
- SSA clusterization approach for avoiding overhead
|
|
- Pipelining function analysis as other approach
|
|
#pause
|
|
#figure(
|
|
caption: [Example function for pipelining analysis, taken from fig. 4 of the work by Shi and Zhang],
|
|
kind: "raw",
|
|
supplement: "",
|
|
```C
|
|
int* foo() {
|
|
int* p = bar(null);
|
|
int* q = p;
|
|
int* r = q;
|
|
return r;
|
|
}
|
|
```
|
|
)
|
|
]
|
|
// research done, some things possible
|
|
// most still sequentially dependent -> not much speedup
|
|
|
|
|
|
= Optimizations
|
|
#slide[
|
|
- Constant folding and propagation
|
|
- `int a = 1; int b = a + 2;` #h(1em) #sym.arrow #h(1em) `int a = 1; int b = 3;`
|
|
#pause
|
|
- Copy propagation
|
|
- `int a; int b = a; int c = b + 1;` #h(1em) #sym.arrow #h(1em) `int a; int c = a + 1;`
|
|
#pause
|
|
- Conditional/Dead branch elimination
|
|
- ` if (false) {...} int a = 4; if (a > 10) {...}` #h(1em) #sym.arrow #h(1em) `int a = 4;`
|
|
#pause
|
|
- Common subexpression elimination
|
|
- `int b = (a + 2) * (a + 2);` #h(1em) #sym.arrow #h(1em) `int temp = a + 2; int b = temp * temp;`
|
|
#pause
|
|
- Dead code elimination
|
|
- `return; int a = 10;` #h(1em) #sym.arrow #h(1em) `return;`
|
|
]
|
|
#v(0mm, weak: true)
|
|
#figure(
|
|
caption: [Example of how RVSDG looks, taken from Fig. 1 of the work by Reissmann, Meyer, Bahmann and Själander],
|
|
grid(
|
|
columns: (1.35fr, 1fr, 1fr),
|
|
column-gutter: 0.5em,
|
|
[
|
|
#set text(size: 15pt)
|
|
#codly(inset: 0.165em)
|
|
```C
|
|
int f(int a, int b, int c, int d) {
|
|
int li1, li2;
|
|
int cse, epr;
|
|
do {
|
|
li1 = b+c;
|
|
li2 = d-b;
|
|
a = a*li1;
|
|
int down = a%c;
|
|
int dead = a+d;
|
|
if (a > d) {
|
|
int acopy = a;
|
|
a = 3+down;
|
|
cse = acopy<<b;
|
|
} else {
|
|
cse = a<<b;
|
|
}
|
|
epr = a<<b;
|
|
} while(a > cse);
|
|
return li2+epr;
|
|
}
|
|
```
|
|
#align(center, text(size: 8.25pt, "(a) Code"))
|
|
],
|
|
image("rvsdg_3_uir.svg", height: 85%),
|
|
image("rvsdg_4_oir.svg", height: 85%),
|
|
|
|
)
|
|
)
|
|
|
|
= Problems with DFA
|
|
// global vars
|
|
// pointers
|
|
// multithreaded
|
|
- Global variables
|
|
- Analysis of every function depends on it
|
|
- Adds complex connections between functions
|
|
#pause
|
|
- Pointer
|
|
- Points-to analysis
|
|
#pause
|
|
- Multithreaded applications
|
|
- Requires well synchronized code
|
|
- Can be handled by build graph of possible concurrent accesses
|
|
|
|
|
|
= Conclusion
|
|
#slide(repeat: 4, self => [
|
|
#let (uncover, only, alternatives) = utils.methods(self)
|
|
|
|
#list(
|
|
[ RQ1 -- What are the advantages and disadvantages of using dataflow analysis for compiler optimization? ] + only("2-", list(
|
|
[Trades compilation performance for runtime performance],
|
|
[Allows complex optimization across branch and function boundaries],
|
|
[Allows writing generic code, which will then be optimized based on the usage in an application]
|
|
))
|
|
)
|
|
#only("3-", list(
|
|
[ RQ2 -- How is dataflow analysis used in current compilers? ] + only("4-", list(
|
|
[Already extensively used by popular compilers],
|
|
[Many different optimizations implemented, some listed previously],
|
|
[Still working on improving speed and optimization possibilities]
|
|
))
|
|
))
|
|
])
|