up
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US"><id>https://alex.vxcc.dev</id><title>alex168's blog</title><updated>2025-08-29T13:28:12.557384+00:00</updated><author><name>Alexander Nutz</name><email>nutz.alexander@vxcc.dev</email><uri>https://alex.vxcc.dev</uri></author><link href="https://alex.vxcc.dev/atom.xml" rel="self"/><link href="https://alex.vxcc.dev/" rel="alternate"/><generator uri="https://lkiesow.github.io/python-feedgen" version="1.0.0">python-feedgen</generator><icon>https://vxcc.dev/alex/res/favicon.png</icon><subtitle>alex_s168's blog</subtitle><entry><id>https://vxcc.dev/alex/compiler-inlining.typ.desktop.html</id><title>Automatically inlining functions is not easy</title><updated>2025-08-11T16:38:10+02:00</updated><author><name>Alexander Nutz</name><email>nutz.alexander@vxcc.dev</email><uri>https://alex.vxcc.dev</uri></author><content type="html"><!DOCTYPE html>
|
||||
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US"><id>https://alex.vxcc.dev</id><title>alex168's blog</title><updated>2025-08-29T13:46:41.354526+00:00</updated><author><name>Alexander Nutz</name><email>nutz.alexander@vxcc.dev</email><uri>https://alex.vxcc.dev</uri></author><link href="https://alex.vxcc.dev/atom.xml" rel="self"/><link href="https://alex.vxcc.dev/" rel="alternate"/><generator uri="https://lkiesow.github.io/python-feedgen" version="1.0.0">python-feedgen</generator><icon>https://vxcc.dev/alex/res/favicon.png</icon><subtitle>alex_s168's blog</subtitle><entry><id>https://vxcc.dev/alex/compiler-inlining.typ.desktop.html</id><title>Automatically inlining functions is not easy</title><updated>2025-08-11T16:38:10+02:00</updated><author><name>Alexander Nutz</name><email>nutz.alexander@vxcc.dev</email><uri>https://alex.vxcc.dev</uri></author><content type="html"><!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Automatically inlining functions is not easy</title>
|
@@ -1,243 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>The making of the favicon</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="icon" sizes="512x512" href="res/favicon.png">
|
||||
<link rel="image_src" type="image/png" href="res/favicon.png">
|
||||
<link type="application/atom+xml" rel="alternate" title="alexs168's blog" href="atom.xml">
|
||||
</head>
|
||||
<body>
|
||||
<style>
|
||||
|
||||
@font-face {
|
||||
font-family: 'DejaVu Sans Mono';
|
||||
src:local('DejaVu Sans Mono'),
|
||||
url('res/DejaVuSansMono.woff2') format('woff2'),
|
||||
local('Courier New'),
|
||||
local(Courier),
|
||||
local(monospace);
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
/*
|
||||
@font-face {
|
||||
font-family: 'DejaVu Sans Mono';
|
||||
src:local('DejaVu Sans Mono'),
|
||||
url('res/DejaVuSansMono-Bold.woff2') format('woff2'),
|
||||
local('Courier New'),
|
||||
local(Courier),
|
||||
local(monospace);
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'DejaVu Sans';
|
||||
src:local('DejaVu Sans'),
|
||||
url('res/DejaVuSans-Bold.woff2') format('woff2'),
|
||||
local('Courier New');
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'DejaVu Sans';
|
||||
src:local('DejaVu Sans'),
|
||||
url('res/DejaVuSans.woff2') format('woff2'),
|
||||
local('Courier New');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}*/
|
||||
|
||||
body {
|
||||
font-family: DejaVu Sans Mono;
|
||||
font-size: 17pt;
|
||||
}
|
||||
|
||||
td {
|
||||
width: 100%;
|
||||
display: inline;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
h1,h2,h3,h4 {
|
||||
margin-top: 1%;
|
||||
margin-bottom: 0.75%;
|
||||
margin-left: -0.75%;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0.75%;
|
||||
margin-bottom: 0.75%;
|
||||
}
|
||||
|
||||
ul {
|
||||
margin-top: 0%;
|
||||
}
|
||||
|
||||
.current {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
pre {
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #3f51b5;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: #3f51b5;
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
<table>
|
||||
<tr>
|
||||
<td><span class="sidebar" style><span class="column-fixed" style="display: inline-flex; position: fixed; justify-content: center; width: 25%"><table><tr><td><span class="table-of-contents" style><div style="
|
||||
border:1.2pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:3%;"><p><span style="text-decoration: underline">Table of contents</span><br></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;"><span class="headingr" id="headingr-0"><a href="#loc-1">Step 0: Designing the Circuit</a></span></span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;"><span class="headingr" id="headingr-1"><a href="#loc-2">Step 1: Sketching</a></span></span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;"><span class="headingr" id="headingr-2"><a href="#loc-3">Step 2: Preparation for coloring</a></span></span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;"><span class="headingr" id="headingr-3"><a href="#loc-4">Step 3: Coloring</a></span></span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;"><span class="headingr" id="headingr-4"><a href="#loc-5">Step 4: Outsourcing the coloring</a></span></span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;"><span class="headingr" id="headingr-5"><a href="#loc-6">Step 5: Digital Modifications</a></span></span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">└─</span> <span class style="flex:1;"><span class="headingr" id="headingr-6"><a href="#loc-7">Conclusion</a></span></span></span></p></div></span><span class="table-of-contents" style><script>document.addEventListener('DOMContentLoaded', function() {
|
||||
let tags = ['h2', 'h3', 'h4'].flatMap(x => Array.from(document.getElementsByTagName(x))).sort((a, b) => a.getBoundingClientRect().top - b.getBoundingClientRect().top);
|
||||
let pageHeight = document.documentElement.scrollHeight-window.innerHeight;
|
||||
document.addEventListener('scroll', (event) => {
|
||||
let progress = -(document.documentElement.getBoundingClientRect().y / pageHeight);
|
||||
let delta = progress * window.innerHeight;
|
||||
let idx = tags.map(x => 0 > x.getBoundingClientRect().top - delta).lastIndexOf(true);
|
||||
Array.from(document.getElementsByClassName('headingr')).map(x => x.classList.remove('current'));
|
||||
if (idx != -1) {
|
||||
document.getElementById('headingr-' + idx).classList.add('current');
|
||||
}
|
||||
}
|
||||
);
|
||||
})</script><style>
|
||||
.table-of-contents > p > span { width: 100%; }
|
||||
</style></span></td></tr><tr><td><br>
|
||||
<a href="index.html"><b>Website Home</b></a> <br>
|
||||
</td></tr><tr><td><p>Renderings of this page:</p><ul><li><a href="#" onclick="gotoVariant(".min.pdf");">minimal PDF (printable)</a></li><li><a href="#" onclick="gotoVariant(".nano.html");">minimal HTML</a></li></ul></td></tr><tr><td><a href="atom.xml">Atom feed</a> <br>
|
||||
</td></tr><tr><td><style>
|
||||
@media only screen and (max-width: 1200px) {
|
||||
.sidebar {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.column-fixed {
|
||||
width: 0% !important;
|
||||
}
|
||||
|
||||
.body-column {
|
||||
left: 3% !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1800px) {
|
||||
.body-column > span {
|
||||
width: 75% !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1200px) {
|
||||
.body-column {
|
||||
width: 97% !important;
|
||||
}
|
||||
.body-column > span {
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
|
||||
.hide { display: inline; background: black; transition: background 0.3s linear; }
|
||||
.hide:hover, .hide:focus { background: transparent; }
|
||||
</style></td></tr></table><style>
|
||||
.column-fixed > table > tbody > tr > td > * { width: 100%; }
|
||||
</style></span></span></td>
|
||||
<td><span class="body-column" style="position: absolute; left: 28%; width: 72%"><span style="
|
||||
|
||||
|
||||
width:50%;
|
||||
|
||||
display:inline-block"><div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><p><br></p><h1>The making of the favicon</h1><p><span style="font-size: 14pt"><p>Git revision <a href="https://github.com/alex-s168/website/tree/c80eb6ef20acd402096f38d45bb40779fa15149b">#c80eb6ef</a><br>Modified at 26. July 2025 15:04</p><p>Written by <a href="https://alex.vxcc.dev">alex_s168</a></p></span></p></div><div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><p><br>The favicon of my website currently is:</p><img src="res/favicon.png" alt="image" style="width:38%;"></div><div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><br>This represents an <a href="https://www.sciencedirect.com/science/article/pii/S0890540197926432">interaction combinator</a> tree, that can be interpreted as a <a href="https://en.wikipedia.org/wiki/Lambda_calculus">lambda calculus</a> expression.</div><div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><p><br><span id="loc-1" style="text-decoration: underline"><h2>Step 0: Designing the Circuit</h2></span> I ended up with this:</p><img src="res/article-favicon/step0.png" alt="image" style="width:32%;"><p>(this is the second attempt at layouting the circuit)</p></div><div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><p><br><span id="loc-2" style="text-decoration: underline"><h2>Step 1: Sketching</h2></span> While starting doing this, I realised that one wire always overlaps with one node triangle, unless I cheated. Here is a visual representation of this (inaccurate):</p><img src="res/article-favicon/step1_0.png" alt="image" style="width:18%;"><p><br>This means that I have to modify the layouting from step 0 a bit, which is unfortunate, but in retrospect, I think that it makes the result look better:</p><img src="res/article-favicon/step1_1.png" alt="image" style="width:25%;"><p><br>That however takes up too much space, so I did another variation:</p><img src="res/article-favicon/step1_2.png" alt="image" style="width:25%;"><p><br>I also did another variation here, but decided to not use that.</p></div><div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><p><br><span id="loc-3" style="text-decoration: underline"><h2>Step 2: Preparation for coloring</h2></span> I colored the back side of the piece of paper which contains the sketeches with a pencil, put a white piece of paper behind it, and then re-traced the line, to get a lighter version of the sketch onto the white paper.</p><img src="res/article-favicon/step2.png" alt="image" style="width:25%;"><p><br>Then I used modern technology (a copier) to copy that piece of paper multiple times, and also scale it up (to allow for more details).</p></div><div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><p><br><span id="loc-4" style="text-decoration: underline"><h2>Step 3: Coloring</h2></span> It was a disaster…</p><img src="res/article-favicon/step3_0.png" alt="image" style="width:70%;"><p><br></p><img src="res/article-favicon/step3_1.png" alt="image" style="width:70%;"><p><br>Some variants actually look nice, but only parts of it.</p></div><div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><p><br><span id="loc-5" style="text-decoration: underline"><h2>Step 4: Outsourcing the coloring</h2></span> After some time, I just gave up, and decided to ask my sister for help…</p><img src="res/article-favicon/step4_0.png" alt="image" style="width:70%;"><p><br>I only told her (translated):</p><div class style="margin-top:4pt;"><span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><pre><code>Can you please color this?<br>It's supposed to be a circuit, and it will be a small logo for a website.<br>The website is mainly black and white, but this (context: persian blue) blue would work too.</code></pre></span></div><p>And less than half a minute later, she came up with this:</p><img src="res/article-favicon/step4_1.png" alt="image" style="width:38%;"><p><br>We considered that the logo will end up being quite small, so “we” wanted it to look good when zoomed out. This is a pretty nice idea, because the different colored wires end up blending together nicely.</p><p><br>I put that into the scanner, and meanwhile she experimented with different filling styles.</p><p><br>Then she came up with this (the final version):</p><img src="res/article-favicon/step4_2.png" alt="image" style="width:38%;"><p>Filling the drawing only took her about 20 seconds!</p></div><div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><br><span id="loc-6" style="text-decoration: underline"><h2>Step 5: Digital Modifications</h2></span> As last step, I removed some of the sketch lines and some minor imperfections digitally.</div><div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><p><br><span id="loc-7" style="text-decoration: underline"><h2>Conclusion</h2></span> I like the final result a lot (as small logo), but it’s a bit too detailed as favicon.</p><p>I will re-visit this topic in the future.</p></div></span></span></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
<script>
|
||||
|
||||
function gotoVariant(variant) {
|
||||
window.location.href = window.location.href.replace(/\.\w+.html/g, variant);
|
||||
}
|
||||
|
||||
window.addEventListener('beforeprint', (event) => {
|
||||
gotoVariant('.min.pdf');
|
||||
});
|
||||
|
||||
</script>
|
||||
<script src="coffee.js" async>
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@@ -1 +0,0 @@
|
||||
build/article-favicon.typ.desktop.html: common.typ pages/article-favicon.typ core-page-style.typ components/header.typ simple-page-layout.typ
|
@@ -1 +0,0 @@
|
||||
--input git_rev=c80eb6ef20acd402096f38d45bb40779fa15149b --input git_commit_date="26. July 2025 15:04"
|
@@ -1 +0,0 @@
|
||||
2025-07-26T15:04:04+02:00
|
@@ -1,232 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>The making of the favicon</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="icon" sizes="512x512" href="res/favicon.png">
|
||||
<link rel="image_src" type="image/png" href="res/favicon.png">
|
||||
<link type="application/atom+xml" rel="alternate" title="alexs168's blog" href="atom.xml">
|
||||
</head>
|
||||
<body>
|
||||
<style>
|
||||
|
||||
@font-face {
|
||||
font-family: 'DejaVu Sans Mono';
|
||||
src:local('DejaVu Sans Mono'),
|
||||
url('res/DejaVuSansMono.woff2') format('woff2'),
|
||||
local('Courier New'),
|
||||
local(Courier),
|
||||
local(monospace);
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
/*
|
||||
@font-face {
|
||||
font-family: 'DejaVu Sans Mono';
|
||||
src:local('DejaVu Sans Mono'),
|
||||
url('res/DejaVuSansMono-Bold.woff2') format('woff2'),
|
||||
local('Courier New'),
|
||||
local(Courier),
|
||||
local(monospace);
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'DejaVu Sans';
|
||||
src:local('DejaVu Sans'),
|
||||
url('res/DejaVuSans-Bold.woff2') format('woff2'),
|
||||
local('Courier New');
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'DejaVu Sans';
|
||||
src:local('DejaVu Sans'),
|
||||
url('res/DejaVuSans.woff2') format('woff2'),
|
||||
local('Courier New');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}*/
|
||||
|
||||
body {
|
||||
font-family: DejaVu Sans Mono;
|
||||
font-size: 10pt;
|
||||
}
|
||||
|
||||
td {
|
||||
width: 100%;
|
||||
display: inline;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
h1,h2,h3,h4 {
|
||||
margin-top: 1%;
|
||||
margin-bottom: 0.75%;
|
||||
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0.75%;
|
||||
margin-bottom: 0.75%;
|
||||
}
|
||||
|
||||
ul {
|
||||
margin-top: 0%;
|
||||
}
|
||||
|
||||
.current {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
pre {
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #3f51b5;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: #3f51b5;
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h1>The making of the favicon</h1>
|
||||
<p><span style="font-size: 9pt"><p>Git revision <a href="https://github.com/alex-s168/website/tree/c80eb6ef20acd402096f38d45bb40779fa15149b">#c80eb6ef</a></p><p><br>Modified at 26. July 2025 15:04</p><p>Written by <a href="https://alex.vxcc.dev">alex_s168</a></p></span></p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br>The favicon of my website currently is:</p>
|
||||
<img src="res/favicon.png" alt="image" style="width:38%;">
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br>This represents an <a href="https://www.sciencedirect.com/science/article/pii/S0890540197926432">interaction combinator</a></p>
|
||||
<p>tree, that can be interpreted as a <a href="https://en.wikipedia.org/wiki/Lambda_calculus">lambda calculus</a></p>
|
||||
<p>expression.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br><span style="text-decoration: underline"><h2>Step 0: Designing the Circuit</h2></span> I ended up with this:</p>
|
||||
<img src="res/article-favicon/step0.png" alt="image" style="width:32%;">
|
||||
<p>(this is the second attempt at layouting the circuit)</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br><span style="text-decoration: underline"><h2>Step 1: Sketching</h2></span> While starting doing this, I realised that one wire always overlaps with one node triangle, unless I cheated. Here is a visual representation of this (inaccurate):</p>
|
||||
<img src="res/article-favicon/step1_0.png" alt="image" style="width:18%;">
|
||||
<p><br>This means that I have to modify the layouting from step 0 a bit, which is unfortunate, but in retrospect, I think that it makes the result look better:</p>
|
||||
<img src="res/article-favicon/step1_1.png" alt="image" style="width:25%;">
|
||||
<p><br>That however takes up too much space, so I did another variation:</p>
|
||||
<img src="res/article-favicon/step1_2.png" alt="image" style="width:25%;">
|
||||
<p><br>I also did another variation here, but decided to not use that.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br><span style="text-decoration: underline"><h2>Step 2: Preparation for coloring</h2></span> I colored the back side of the piece of paper which contains the sketeches with a pencil, put a white piece of paper behind it, and then re-traced the line, to get a lighter version of the sketch onto the white paper.</p>
|
||||
<img src="res/article-favicon/step2.png" alt="image" style="width:25%;">
|
||||
<p><br>Then I used modern technology (a copier) to copy that piece of paper multiple times, and also scale it up (to allow for more details).</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br><span style="text-decoration: underline"><h2>Step 3: Coloring</h2></span> It was a disaster…</p>
|
||||
<img src="res/article-favicon/step3_0.png" alt="image" style="width:70%;">
|
||||
<p><br></p>
|
||||
<img src="res/article-favicon/step3_1.png" alt="image" style="width:70%;">
|
||||
<p><br>Some variants actually look nice, but only parts of it.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br><span style="text-decoration: underline"><h2>Step 4: Outsourcing the coloring</h2></span> After some time, I just gave up, and decided to ask my sister for help…</p>
|
||||
<img src="res/article-favicon/step4_0.png" alt="image" style="width:70%;">
|
||||
<p><br>I only told her (translated):</p>
|
||||
<div class style="margin-top:4pt;"><span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><pre><code>Can you please color this?<br>It's supposed to be a circuit, and it will be a small logo for a website.<br>The website is mainly black and white, but this (context: persian blue) blue would work too.</code></pre></span></div>
|
||||
<p>And less than half a minute later, she came up with this:</p>
|
||||
<img src="res/article-favicon/step4_1.png" alt="image" style="width:38%;">
|
||||
<p><br>We considered that the logo will end up being quite small, so “we” wanted it to look good when zoomed out. This is a pretty nice idea, because the different colored wires end up blending together nicely.</p>
|
||||
<p><br>I put that into the scanner, and meanwhile she experimented with different filling styles.</p>
|
||||
<p><br>Then she came up with this (the final version):</p>
|
||||
<img src="res/article-favicon/step4_2.png" alt="image" style="width:38%;">
|
||||
<p>Filling the drawing only took her about 20 seconds!</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><br><span style="text-decoration: underline"><h2>Step 5: Digital Modifications</h2></span> As last step, I removed some of the sketch lines and some minor imperfections digitally.</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br><span style="text-decoration: underline"><h2>Conclusion</h2></span> I like the final result a lot (as small logo), but it’s a bit too detailed as favicon.</p>
|
||||
<p>I will re-visit this topic in the future.</p>
|
||||
</div>
|
||||
<script>
|
||||
|
||||
function gotoVariant(variant) {
|
||||
window.location.href = window.location.href.replace(/\.\w+.html/g, variant);
|
||||
}
|
||||
|
||||
window.addEventListener('beforeprint', (event) => {
|
||||
gotoVariant('.min.pdf');
|
||||
});
|
||||
|
||||
</script>
|
||||
<script src="coffee.js" async>
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@@ -1 +0,0 @@
|
||||
build/article-favicon.typ.min.html: common.typ pages/article-favicon.typ core-page-style.typ components/header.typ simple-page-layout.typ
|
@@ -1 +0,0 @@
|
||||
build/article-favicon.typ.min.pdf: res/article-favicon/step1_2.png common.typ res/article-favicon/step3_1.png components/header.typ res/article-favicon/step4_2.png res/article-favicon/step1_0.png pages/article-favicon.typ res/article-favicon/step2.png simple-page-layout.typ res/article-favicon/step4_0.png res/favicon.png res/article-favicon/step1_1.png res/article-favicon/step3_0.png core-page-style.typ res/article-favicon/step4_1.png res/article-favicon/step0.png
|
@@ -1,129 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>The making of the favicon</title>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h1>The making of the favicon</h1>
|
||||
<p><span style="font-size: 9pt"><p>Last modified: 26. July 2025 15:04 (Git #<code><code style="white-space: pre-wrap">c80eb6ef</code></code>)</p><p>Written by <a href="https://alex.vxcc.dev">alex_s168</a></p></span></p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br>The favicon of my website currently is:</p>
|
||||
<img src="res/favicon.png" alt="image" style="width:38%;">
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><br>This represents an <a href="https://www.sciencedirect.com/science/article/pii/S0890540197926432">interaction combinator</a> tree, that can be interpreted as a <a href="https://en.wikipedia.org/wiki/Lambda_calculus">lambda calculus</a> expression.</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h2>Step 0: Designing the Circuit</h2>
|
||||
<p>I ended up with this:</p>
|
||||
<img src="res/article-favicon/step0.png" alt="image" style="width:32%;">
|
||||
<p>(this is the second attempt at layouting the circuit)</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h2>Step 1: Sketching</h2>
|
||||
<p>While starting doing this, I realised that one wire always overlaps with one node triangle, unless I cheated. Here is a visual representation of this (inaccurate):</p>
|
||||
<img src="res/article-favicon/step1_0.png" alt="image" style="width:18%;">
|
||||
<p><br>This means that I have to modify the layouting from step 0 a bit, which is unfortunate, but in retrospect, I think that it makes the result look better:</p>
|
||||
<img src="res/article-favicon/step1_1.png" alt="image" style="width:25%;">
|
||||
<p><br>That however takes up too much space, so I did another variation:</p>
|
||||
<img src="res/article-favicon/step1_2.png" alt="image" style="width:25%;">
|
||||
<p><br>I also did another variation here, but decided to not use that.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h2>Step 2: Preparation for coloring</h2>
|
||||
<p>I colored the back side of the piece of paper which contains the sketeches with a pencil, put a white piece of paper behind it, and then re-traced the line, to get a lighter version of the sketch onto the white paper.</p>
|
||||
<img src="res/article-favicon/step2.png" alt="image" style="width:25%;">
|
||||
<p><br>Then I used modern technology (a copier) to copy that piece of paper multiple times, and also scale it up (to allow for more details).</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h2>Step 3: Coloring</h2>
|
||||
<p>It was a disaster…</p>
|
||||
<img src="res/article-favicon/step3_0.png" alt="image" style="width:70%;">
|
||||
<p><br></p>
|
||||
<img src="res/article-favicon/step3_1.png" alt="image" style="width:70%;">
|
||||
<p><br>Some variants actually look nice, but only parts of it.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h2>Step 4: Outsourcing the coloring</h2>
|
||||
<p>After some time, I just gave up, and decided to ask my sister for help…</p>
|
||||
<img src="res/article-favicon/step4_0.png" alt="image" style="width:70%;">
|
||||
<p><br>I only told her (translated):</p>
|
||||
<p><code><pre><code>Can you please color this?<br>It's supposed to be a circuit, and it will be a small logo for a website.<br>The website is mainly black and white, but this (context: persian blue) blue would work too.</code></pre></code></p>
|
||||
<p>And less than half a minute later, she came up with this:</p>
|
||||
<img src="res/article-favicon/step4_1.png" alt="image" style="width:38%;">
|
||||
<p><br>We considered that the logo will end up being quite small, so “we” wanted it to look good when zoomed out. This is a pretty nice idea, because the different colored wires end up blending together nicely.</p>
|
||||
<p><br>I put that into the scanner, and meanwhile she experimented with different filling styles.</p>
|
||||
<p><br>Then she came up with this (the final version):</p>
|
||||
<img src="res/article-favicon/step4_2.png" alt="image" style="width:38%;">
|
||||
<p>Filling the drawing only took her about 20 seconds!</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h2>Step 5: Digital Modifications</h2>
|
||||
<p>As last step, I removed some of the sketch lines and some minor imperfections digitally.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h2>Conclusion</h2>
|
||||
<p>I like the final result a lot (as small logo), but it’s a bit too detailed as favicon.</p>
|
||||
<p>I will re-visit this topic in the future.</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@@ -1 +0,0 @@
|
||||
build/article-favicon.typ.nano.html: common.typ pages/article-favicon.typ core-page-style.typ components/header.typ simple-page-layout.typ
|
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
||||
build/article-gpu-arch-1.typ.desktop.html: common.typ pages/article-gpu-arch-1.typ core-page-style.typ components/header.typ simple-page-layout.typ
|
@@ -1 +0,0 @@
|
||||
--input git_rev=5a9dfdd720bcba1e5d1562279e09c674a30a174b --input git_commit_date="26. August 2025 21:13"
|
@@ -1 +0,0 @@
|
||||
2025-08-26T21:13:01+02:00
|
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
||||
build/article-gpu-arch-1.typ.min.html: common.typ pages/article-gpu-arch-1.typ core-page-style.typ components/header.typ simple-page-layout.typ
|
@@ -1 +0,0 @@
|
||||
build/article-gpu-arch-1.typ.min.pdf: common.typ pages/article-gpu-arch-1.typ core-page-style.typ components/header.typ simple-page-layout.typ
|
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
||||
build/article-gpu-arch-1.typ.nano.html: common.typ pages/article-gpu-arch-1.typ core-page-style.typ components/header.typ simple-page-layout.typ
|
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
||||
build/article-make-regex-engine-1.typ.desktop.html: common.typ pages/article-make-regex-engine-1.typ core-page-style.typ components/header.typ simple-page-layout.typ
|
@@ -1 +0,0 @@
|
||||
--input git_rev=fee2a36453b624f2e6ede5186b5f3e59aa3e6cc7 --input git_commit_date="26. July 2025 14:20"
|
@@ -1 +0,0 @@
|
||||
2025-07-26T14:20:22+02:00
|
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
||||
build/article-make-regex-engine-1.typ.min.html: common.typ pages/article-make-regex-engine-1.typ core-page-style.typ components/header.typ simple-page-layout.typ
|
@@ -1 +0,0 @@
|
||||
build/article-make-regex-engine-1.typ.min.pdf: common.typ pages/article-make-regex-engine-1.typ core-page-style.typ components/header.typ simple-page-layout.typ
|
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
||||
build/article-make-regex-engine-1.typ.nano.html: common.typ pages/article-make-regex-engine-1.typ core-page-style.typ components/header.typ simple-page-layout.typ
|
@@ -1,3 +0,0 @@
|
||||
alex https://alex.vxcc.dev/res/badge.png
|
||||
ote https://512b.dev/assets/lagtrain.gif
|
||||
syn https://512b.dev/syn/badge.png
|
Binary file not shown.
@@ -1,358 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Automatically inlining functions is not easy</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="icon" sizes="512x512" href="res/favicon.png">
|
||||
<link rel="image_src" type="image/png" href="res/favicon.png">
|
||||
<link type="application/atom+xml" rel="alternate" title="alexs168's blog" href="atom.xml">
|
||||
</head>
|
||||
<body>
|
||||
<style>
|
||||
|
||||
@font-face {
|
||||
font-family: 'DejaVu Sans Mono';
|
||||
src:local('DejaVu Sans Mono'),
|
||||
url('res/DejaVuSansMono.woff2') format('woff2'),
|
||||
local('Courier New'),
|
||||
local(Courier),
|
||||
local(monospace);
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
/*
|
||||
@font-face {
|
||||
font-family: 'DejaVu Sans Mono';
|
||||
src:local('DejaVu Sans Mono'),
|
||||
url('res/DejaVuSansMono-Bold.woff2') format('woff2'),
|
||||
local('Courier New'),
|
||||
local(Courier),
|
||||
local(monospace);
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'DejaVu Sans';
|
||||
src:local('DejaVu Sans'),
|
||||
url('res/DejaVuSans-Bold.woff2') format('woff2'),
|
||||
local('Courier New');
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'DejaVu Sans';
|
||||
src:local('DejaVu Sans'),
|
||||
url('res/DejaVuSans.woff2') format('woff2'),
|
||||
local('Courier New');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}*/
|
||||
|
||||
body {
|
||||
font-family: DejaVu Sans Mono;
|
||||
font-size: 17pt;
|
||||
}
|
||||
|
||||
td {
|
||||
width: 100%;
|
||||
display: inline;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
h1,h2,h3,h4 {
|
||||
margin-top: 1%;
|
||||
margin-bottom: 0.75%;
|
||||
margin-left: -0.75%;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0.75%;
|
||||
margin-bottom: 0.75%;
|
||||
}
|
||||
|
||||
ul {
|
||||
margin-top: 0%;
|
||||
}
|
||||
|
||||
.current {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
pre {
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #3f51b5;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: #3f51b5;
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
<table>
|
||||
<tr>
|
||||
<td><span class="sidebar" style><span class="column-fixed" style="display: inline-flex; position: fixed; justify-content: center; width: 25%"><table><tr><td><span class="table-of-contents" style><div style="
|
||||
border:1.2pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:3%;"><p><span style="text-decoration: underline">Table of contents</span><br></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;"><span class="headingr" id="headingr-0"><a href="#loc-1">Introduction</a></span></span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;"><span class="headingr" id="headingr-1"><a href="#loc-2">Greedy inlining with heuristics</a></span></span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">| ├─</span> <span class style="flex:1;"><span class="headingr" id="headingr-2"><a href="#loc-3">Issue 1: (sometimes) multiple options</a></span></span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">| ├─</span> <span class style="flex:1;"><span class="headingr" id="headingr-3"><a href="#loc-4">Issue 2: ABI requirements on argument passing</a></span></span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">| └─</span> <span class style="flex:1;"><span class="headingr" id="headingr-4"><a href="#loc-5">Issue 3: (sometimes) prevents optimizations</a></span></span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;"><span class="headingr" id="headingr-5"><a href="#loc-6">Function outlining</a></span></span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;"><span class="headingr" id="headingr-6"><a href="#loc-7">A better approach</a></span></span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">| ├─</span> <span class style="flex:1;"><span class="headingr" id="headingr-7"><a href="#loc-8">Step 1: inlining</a></span></span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">| ├─</span> <span class style="flex:1;"><span class="headingr" id="headingr-8"><a href="#loc-9">Step 2: detect duplicate code</a></span></span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">| ├─</span> <span class style="flex:1;"><span class="headingr" id="headingr-9"><a href="#loc-10">Step 3: slightly reduce size of outlinable section</a></span></span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">| ├─</span> <span class style="flex:1;"><span class="headingr" id="headingr-10"><a href="#loc-11">Step 4: perform outlining</a></span></span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">| └─</span> <span class style="flex:1;"><span class="headingr" id="headingr-11"><a href="#loc-12">Issue 1: high compile-time memory usage</a></span></span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">└─</span> <span class style="flex:1;"><span class="headingr" id="headingr-12"><a href="#loc-13">Conclusion</a></span></span></span></p></div></span><span class="table-of-contents" style><script>document.addEventListener('DOMContentLoaded', function() {
|
||||
let tags = ['h2', 'h3', 'h4'].flatMap(x => Array.from(document.getElementsByTagName(x))).sort((a, b) => a.getBoundingClientRect().top - b.getBoundingClientRect().top);
|
||||
let pageHeight = document.documentElement.scrollHeight-window.innerHeight;
|
||||
document.addEventListener('scroll', (event) => {
|
||||
let progress = -(document.documentElement.getBoundingClientRect().y / pageHeight);
|
||||
let delta = progress * window.innerHeight;
|
||||
let idx = tags.map(x => 0 > x.getBoundingClientRect().top - delta).lastIndexOf(true);
|
||||
Array.from(document.getElementsByClassName('headingr')).map(x => x.classList.remove('current'));
|
||||
if (idx != -1) {
|
||||
document.getElementById('headingr-' + idx).classList.add('current');
|
||||
}
|
||||
}
|
||||
);
|
||||
})</script><style>
|
||||
.table-of-contents > p > span { width: 100%; }
|
||||
</style></span></td></tr><tr><td><br>
|
||||
<a href="index.html"><b>Website Home</b></a> <br>
|
||||
</td></tr><tr><td><p>Renderings of this page:</p><ul><li><a href="#" onclick="gotoVariant(".min.pdf");">minimal PDF (printable)</a></li><li><a href="#" onclick="gotoVariant(".nano.html");">minimal HTML</a></li></ul></td></tr><tr><td><a href="atom.xml">Atom feed</a> <br>
|
||||
</td></tr><tr><td><style>
|
||||
@media only screen and (max-width: 1200px) {
|
||||
.sidebar {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.column-fixed {
|
||||
width: 0% !important;
|
||||
}
|
||||
|
||||
.body-column {
|
||||
left: 3% !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1800px) {
|
||||
.body-column > span {
|
||||
width: 75% !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1200px) {
|
||||
.body-column {
|
||||
width: 97% !important;
|
||||
}
|
||||
.body-column > span {
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
|
||||
.hide { display: inline; background: black; transition: background 0.3s linear; }
|
||||
.hide:hover, .hide:focus { background: transparent; }
|
||||
</style></td></tr></table><style>
|
||||
.column-fixed > table > tbody > tr > td > * { width: 100%; }
|
||||
</style></span></span></td>
|
||||
<td><span class="body-column" style="position: absolute; left: 28%; width: 72%"><span style="
|
||||
|
||||
|
||||
width:50%;
|
||||
|
||||
display:inline-block"><div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><p><br></p><h1>Automatically inlining functions is not easy</h1><p><span style="font-size: 14pt"><p>Git revision <a href="https://github.com/alex-s168/website/tree/9c2913af189b62c028f6f773370f50f9e6c13307">#9c2913af</a><br>Modified at 11. August 2025 16:38</p><p>Written by <a href="https://alex.vxcc.dev">alex_s168</a></p></span></p></div><div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><br>Note that the <a href="#" onclick="gotoVariant(".min.pdf");">PDF Version</a> of this page might look a bit better styling wise.</div><div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><br><span id="loc-1" style="text-decoration: underline"><h2>Introduction</h2></span> Function calls have some overhead, which can sometimes be a big issue for other optimizations. Because of that, compiler backends (should) inline function calls. There are however many issues with just greedily inlining calls…</div><div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><p><br><span id="loc-2" style="text-decoration: underline"><h2>Greedy inlining with heuristics</h2></span> This is the most obvious approach. We can just inline all functions with only one call, and then inline calls where the inlined function does not have many instructions.</p><p>Example:</p><div class style="margin-top:4pt;"><span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><pre><code>function f32 $square(f32 %x) {<br>@entry:<br> // this is stupid, but I couldn't come up with a better example<br> f32 %e = add %x, 0<br> f32 %out = add %e, %x<br> ret %out<br>}<br><br>function f32 $hypot(f32 %a, f32 %b) {<br>@entry:<br> f32 %as = call $square(%a)<br> f32 %bs = call $square(%b)<br> f32 %sum = add %as, %bs<br> f32 %o = sqrt %sum<br> ret %o<br>}<br><br>function f32 $tri_hypot({f32, f32} %x) {<br> f32 %a = extract %x, 0<br> f32 %b = extract %x, 1<br> f32 %o = call $hypot(%a, %b) // this is a "tail call"<br> ret %o<br>}<br><br>// let's assume that $hypot is used someplace else in the code too</code></pre></span></div></div><div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><br>Let’s assume our inlining treshold is 5 operations. Then we would get – Waait there are multiple options…</div><div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><p><br><span id="loc-3" style="text-decoration: underline"><h3>Issue 1: (sometimes) multiple options</h3></span> If we inline the <span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><code style="white-space: pre-wrap">$square</code></span> calls, then <span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><code style="white-space: pre-wrap">$hypot</code></span> will have too many instructions to be inlined into <span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><code style="white-space: pre-wrap">$tri_hypot</code></span>:</p><div class style="margin-top:4pt;"><span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><pre><code>...<br>function f32 $hypot(f32 %a, f32 %b) {<br>@entry:<br> // more instructions than our inlining treshold:<br> f32 %ase = add %a, 0<br> f32 %as = add %ase, %a<br> f32 %bse = add %b, 0<br> f32 %bs = add %bse, %b<br> f32 %sum = add %as, %bs<br> f32 %o = sqrt %sum<br> ret %o<br>}<br>...</code></pre></span></div></div><div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><p><br>The second option is to inline the <span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><code style="white-space: pre-wrap">$hypot</code></span> call into <span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><code style="white-space: pre-wrap">$tri_hypot</code></span>. (There are also some other options)</p><p>Now in this case, it seems obvious to prefer inlining <span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><code style="white-space: pre-wrap">$square</code></span> into <span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><code style="white-space: pre-wrap">$hypot</code></span>.</p></div><div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><p><br><span id="loc-4" style="text-decoration: underline"><h3>Issue 2: ABI requirements on argument passing</h3></span> If we assume the target ABI only has one f32 register for passing arguments, then we would have to generate additional instructions for passing the second argument of <span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><code style="white-space: pre-wrap">$hypot</code></span>, and then it might actually be more efficient to inline <span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><code style="white-space: pre-wrap">$hypot</code></span> instead of <span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><code style="white-space: pre-wrap">$square</code></span>.</p><p>This example is not realistic, but this issue actually occurs when compiling lots of code.</p><p>Another related issue is that having more arguments arranged in a fixed way will require lots of moving data arround at the call site.</p><p>A solution to this is to make the heuristics not just output code size, but also make it depend on the number of arguments / outputs passed to the function.</p></div><div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><p><br><span id="loc-5" style="text-decoration: underline"><h3>Issue 3: (sometimes) prevents optimizations</h3></span></p><div class style="margin-top:4pt;"><span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><pre><code>function f32 $myfunc(f32 %a, f32 %b) {<br>@entry:<br> f32 %sum = add %a, %b<br> f32 %sq = sqrt %sum<br> ...<br>}<br><br>function $callsite(f32 %a, f32 %b) {<br>@entry:<br> f32 %as = add %a, %a<br> f32 %bs = add %b, %b<br> f32 %x = call $myfunc(%as, %bs)<br> ...<br>}</code></pre></span></div><p>If the target has a efficient <span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><code style="white-space: pre-wrap">hypot</code></span> operation, then that operation will only be used if we inline <span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><code style="white-space: pre-wrap">$myfunc</code></span> into <span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><code style="white-space: pre-wrap">$callsite</code></span>.</p><p>This means that inlining is now depended on… instruction selection??</p><p>This is not the only optimization prevented by not inlining the call. If <span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><code style="white-space: pre-wrap">$callsite</code></span> were to be called in a loop, then not inlining would prevent vectorization.</p></div><div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><p><br><span id="loc-6" style="text-decoration: underline"><h2>Function outlining</h2></span> A related optimization is “outlining”. It’s the opposite to inlining. It moves duplicate code into a function, to reduce code size, and sometimes increase performance (because of instruction caching)</p><p>If we do inlining seperately from outlining, we often get unoptimal code.</p></div><div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><br><span id="loc-7" style="text-decoration: underline"><h2>A better approach</h2></span> We can instead first inline <strong>all</strong> inlinable calls, and <strong>then</strong> perform more agressive outlining.</div><div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><p><br><span id="loc-8" style="text-decoration: underline"><h3>Step 1: inlining</h3></span> We inline <strong>all</strong> function calls, except for:</p><ul><li>self recursion (obviously)</li><li>functions explicitly marked as no-inline by the user</li></ul></div><div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><p><br><span id="loc-9" style="text-decoration: underline"><h3>Step 2: detect duplicate code</h3></span> There are many algorithms for doing this.</p><p>The goal of this step is to both:</p><ul><li>maximize size of outlinable section</li><li>minimize size of code</li></ul></div><div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><p><br><span id="loc-10" style="text-decoration: underline"><h3>Step 3: slightly reduce size of outlinable section</h3></span> The goal is to reduce size of outlinable sections, to make the code more optimal.</p><p>This should be ABI and instruction depended, and have the goal of:</p><ul><li>reducing argument shuffles required at all call sites</li><li>reducing register preassure</li><li>not preventing good isel choices and optimizations.</li></ul><p>this is also dependent on the targetted code size.</p></div><div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><br><span id="loc-11" style="text-decoration: underline"><h3>Step 4: perform outlining</h3></span> This is obvious.</div><div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><p><br><span id="loc-12" style="text-decoration: underline"><h3>Issue 1: high compile-time memory usage</h3></span> Inlining <strong>all</strong> function calls first will increase the memory usage during compilation by A LOT</p><p>I’m sure that there is a smarter way to implement this method, without actually performing the inlining…</p></div><div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><p><br><span id="loc-13" style="text-decoration: underline"><h2>Conclusion</h2></span> Function inlining is much more complex than one might think.</p><p>PS: No idea how to implement this…</p><p>Subscribe to the <a href="atom.xml">Atom feed</a> to get notified about futre compiler-related articles.</p></div></span></span></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
<script>
|
||||
|
||||
function gotoVariant(variant) {
|
||||
window.location.href = window.location.href.replace(/\.\w+.html/g, variant);
|
||||
}
|
||||
|
||||
window.addEventListener('beforeprint', (event) => {
|
||||
gotoVariant('.min.pdf');
|
||||
});
|
||||
|
||||
</script>
|
||||
<script src="coffee.js" async>
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@@ -1 +0,0 @@
|
||||
build/compiler-inlining.typ.desktop.html: common.typ pages/compiler-inlining.typ core-page-style.typ components/header.typ simple-page-layout.typ
|
@@ -1 +0,0 @@
|
||||
--input git_rev=9c2913af189b62c028f6f773370f50f9e6c13307 --input git_commit_date="11. August 2025 16:38"
|
@@ -1 +0,0 @@
|
||||
2025-08-11T16:38:10+02:00
|
@@ -1,358 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Automatically inlining functions is not easy</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="icon" sizes="512x512" href="res/favicon.png">
|
||||
<link rel="image_src" type="image/png" href="res/favicon.png">
|
||||
<link type="application/atom+xml" rel="alternate" title="alexs168's blog" href="atom.xml">
|
||||
</head>
|
||||
<body>
|
||||
<style>
|
||||
|
||||
@font-face {
|
||||
font-family: 'DejaVu Sans Mono';
|
||||
src:local('DejaVu Sans Mono'),
|
||||
url('res/DejaVuSansMono.woff2') format('woff2'),
|
||||
local('Courier New'),
|
||||
local(Courier),
|
||||
local(monospace);
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
/*
|
||||
@font-face {
|
||||
font-family: 'DejaVu Sans Mono';
|
||||
src:local('DejaVu Sans Mono'),
|
||||
url('res/DejaVuSansMono-Bold.woff2') format('woff2'),
|
||||
local('Courier New'),
|
||||
local(Courier),
|
||||
local(monospace);
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'DejaVu Sans';
|
||||
src:local('DejaVu Sans'),
|
||||
url('res/DejaVuSans-Bold.woff2') format('woff2'),
|
||||
local('Courier New');
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'DejaVu Sans';
|
||||
src:local('DejaVu Sans'),
|
||||
url('res/DejaVuSans.woff2') format('woff2'),
|
||||
local('Courier New');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}*/
|
||||
|
||||
body {
|
||||
font-family: DejaVu Sans Mono;
|
||||
font-size: 10pt;
|
||||
}
|
||||
|
||||
td {
|
||||
width: 100%;
|
||||
display: inline;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
h1,h2,h3,h4 {
|
||||
margin-top: 1%;
|
||||
margin-bottom: 0.75%;
|
||||
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0.75%;
|
||||
margin-bottom: 0.75%;
|
||||
}
|
||||
|
||||
ul {
|
||||
margin-top: 0%;
|
||||
}
|
||||
|
||||
.current {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
pre {
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #3f51b5;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: #3f51b5;
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h1>Automatically inlining functions is not easy</h1>
|
||||
<p><span style="font-size: 9pt"><p>Git revision <a href="https://github.com/alex-s168/website/tree/9c2913af189b62c028f6f773370f50f9e6c13307">#9c2913af</a></p><p><br>Modified at 11. August 2025 16:38</p><p>Written by <a href="https://alex.vxcc.dev">alex_s168</a></p></span></p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><br><span style="text-decoration: underline"><h2>Introduction</h2></span> Function calls have some overhead, which can sometimes be a big issue for other optimizations. Because of that, compiler backends (should) inline function calls. There are however many issues with just greedily inlining calls…</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br><span style="text-decoration: underline"><h2>Greedy inlining with heuristics</h2></span> This is the most obvious approach. We can just inline all functions with only one call, and then inline calls where the inlined function does not have many instructions.</p>
|
||||
<p>Example:</p>
|
||||
<div class style="margin-top:4pt;"><span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><pre><code>function f32 $square(f32 %x) {<br>@entry:<br> // this is stupid, but I couldn't come up with a better example<br> f32 %e = add %x, 0<br> f32 %out = add %e, %x<br> ret %out<br>}<br><br>function f32 $hypot(f32 %a, f32 %b) {<br>@entry:<br> f32 %as = call $square(%a)<br> f32 %bs = call $square(%b)<br> f32 %sum = add %as, %bs<br> f32 %o = sqrt %sum<br> ret %o<br>}<br><br>function f32 $tri_hypot({f32, f32} %x) {<br> f32 %a = extract %x, 0<br> f32 %b = extract %x, 1<br> f32 %o = call $hypot(%a, %b) // this is a "tail call"<br> ret %o<br>}<br><br>// let's assume that $hypot is used someplace else in the code too</code></pre></span></div>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><br>Let’s assume our inlining treshold is 5 operations. Then we would get – Waait there are multiple options…</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br><span style="text-decoration: underline"><h3>Issue 1: (sometimes) multiple options</h3></span> If we inline the <span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><code style="white-space: pre-wrap">$square</code></span> calls, then <span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><code style="white-space: pre-wrap">$hypot</code></span> will have too many instructions to be inlined into <span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><code style="white-space: pre-wrap">$tri_hypot</code></span>:</p>
|
||||
<div class style="margin-top:4pt;"><span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><pre><code>...<br>function f32 $hypot(f32 %a, f32 %b) {<br>@entry:<br> // more instructions than our inlining treshold:<br> f32 %ase = add %a, 0<br> f32 %as = add %ase, %a<br> f32 %bse = add %b, 0<br> f32 %bs = add %bse, %b<br> f32 %sum = add %as, %bs<br> f32 %o = sqrt %sum<br> ret %o<br>}<br>...</code></pre></span></div>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br>The second option is to inline the <span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><code style="white-space: pre-wrap">$hypot</code></span> call into <span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><code style="white-space: pre-wrap">$tri_hypot</code></span>. (There are also some other options)</p>
|
||||
<p>Now in this case, it seems obvious to prefer inlining <span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><code style="white-space: pre-wrap">$square</code></span> into <span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><code style="white-space: pre-wrap">$hypot</code></span>.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br><span style="text-decoration: underline"><h3>Issue 2: ABI requirements on argument passing</h3></span> If we assume the target ABI only has one f32 register for passing arguments, then we would have to generate additional instructions for passing the second argument of <span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><code style="white-space: pre-wrap">$hypot</code></span>, and then it might actually be more efficient to inline <span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><code style="white-space: pre-wrap">$hypot</code></span> instead of <span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><code style="white-space: pre-wrap">$square</code></span>.</p>
|
||||
<p>This example is not realistic, but this issue actually occurs when compiling lots of code.</p>
|
||||
<p>Another related issue is that having more arguments arranged in a fixed way will require lots of moving data arround at the call site.</p>
|
||||
<p>A solution to this is to make the heuristics not just output code size, but also make it depend on the number of arguments / outputs passed to the function.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br><span style="text-decoration: underline"><h3>Issue 3: (sometimes) prevents optimizations</h3></span></p>
|
||||
<div class style="margin-top:4pt;"><span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><pre><code>function f32 $myfunc(f32 %a, f32 %b) {<br>@entry:<br> f32 %sum = add %a, %b<br> f32 %sq = sqrt %sum<br> ...<br>}<br><br>function $callsite(f32 %a, f32 %b) {<br>@entry:<br> f32 %as = add %a, %a<br> f32 %bs = add %b, %b<br> f32 %x = call $myfunc(%as, %bs)<br> ...<br>}</code></pre></span></div>
|
||||
<p>If the target has a efficient <span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><code style="white-space: pre-wrap">hypot</code></span> operation, then that operation will only be used if we inline <span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><code style="white-space: pre-wrap">$myfunc</code></span> into <span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><code style="white-space: pre-wrap">$callsite</code></span>.</p>
|
||||
<p>This means that inlining is now depended on… instruction selection??</p>
|
||||
<p>This is not the only optimization prevented by not inlining the call. If <span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><code style="white-space: pre-wrap">$callsite</code></span> were to be called in a loop, then not inlining would prevent vectorization.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br><span style="text-decoration: underline"><h2>Function outlining</h2></span> A related optimization is “outlining”. It’s the opposite to inlining. It moves duplicate code into a function, to reduce code size, and sometimes increase performance (because of instruction caching)</p>
|
||||
<p>If we do inlining seperately from outlining, we often get unoptimal code.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><br><span style="text-decoration: underline"><h2>A better approach</h2></span> We can instead first inline <strong>all</strong> inlinable calls, and <strong>then</strong> perform more agressive outlining.</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br><span style="text-decoration: underline"><h3>Step 1: inlining</h3></span> We inline <strong>all</strong> function calls, except for:</p>
|
||||
<ul>
|
||||
<li>self recursion (obviously)</li>
|
||||
<li>functions explicitly marked as no-inline by the user</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br><span style="text-decoration: underline"><h3>Step 2: detect duplicate code</h3></span> There are many algorithms for doing this.</p>
|
||||
<p>The goal of this step is to both:</p>
|
||||
<ul>
|
||||
<li>maximize size of outlinable section</li>
|
||||
<li>minimize size of code</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br><span style="text-decoration: underline"><h3>Step 3: slightly reduce size of outlinable section</h3></span> The goal is to reduce size of outlinable sections, to make the code more optimal.</p>
|
||||
<p>This should be ABI and instruction depended, and have the goal of:</p>
|
||||
<ul>
|
||||
<li>reducing argument shuffles required at all call sites</li>
|
||||
<li>reducing register preassure</li>
|
||||
<li>not preventing good isel choices and optimizations.</li>
|
||||
</ul>
|
||||
<p>this is also dependent on the targetted code size.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><br><span style="text-decoration: underline"><h3>Step 4: perform outlining</h3></span> This is obvious.</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br><span style="text-decoration: underline"><h3>Issue 1: high compile-time memory usage</h3></span> Inlining <strong>all</strong> function calls first will increase the memory usage during compilation by A LOT</p>
|
||||
<p>I’m sure that there is a smarter way to implement this method, without actually performing the inlining…</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br><span style="text-decoration: underline"><h2>Conclusion</h2></span> Function inlining is much more complex than one might think.</p>
|
||||
<p>PS: No idea how to implement this…</p>
|
||||
<p>Subscribe to the <a href="atom.xml">Atom feed</a></p>
|
||||
<p>to get notified about futre compiler-related articles.</p>
|
||||
</div>
|
||||
<script>
|
||||
|
||||
function gotoVariant(variant) {
|
||||
window.location.href = window.location.href.replace(/\.\w+.html/g, variant);
|
||||
}
|
||||
|
||||
window.addEventListener('beforeprint', (event) => {
|
||||
gotoVariant('.min.pdf');
|
||||
});
|
||||
|
||||
</script>
|
||||
<script src="coffee.js" async>
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@@ -1 +0,0 @@
|
||||
build/compiler-inlining.typ.min.html: common.typ pages/compiler-inlining.typ core-page-style.typ components/header.typ simple-page-layout.typ
|
@@ -1 +0,0 @@
|
||||
build/compiler-inlining.typ.min.pdf: common.typ pages/compiler-inlining.typ core-page-style.typ components/header.typ simple-page-layout.typ
|
@@ -1,193 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Automatically inlining functions is not easy</title>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h1>Automatically inlining functions is not easy</h1>
|
||||
<p><span style="font-size: 9pt"><p>Last modified: 11. August 2025 16:38 (Git #<code><code style="white-space: pre-wrap">9c2913af</code></code>)</p><p>Written by <a href="https://alex.vxcc.dev">alex_s168</a></p></span></p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h2>Introduction</h2>
|
||||
<p>Function calls have some overhead, which can sometimes be a big issue for other optimizations. Because of that, compiler backends (should) inline function calls. There are however many issues with just greedily inlining calls…</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h2>Greedy inlining with heuristics</h2>
|
||||
<p>This is the most obvious approach. We can just inline all functions with only one call, and then inline calls where the inlined function does not have many instructions.</p>
|
||||
<p>Example:</p>
|
||||
<p><code><pre><code>function f32 $square(f32 %x) {<br>@entry:<br> // this is stupid, but I couldn't come up with a better example<br> f32 %e = add %x, 0<br> f32 %out = add %e, %x<br> ret %out<br>}<br><br>function f32 $hypot(f32 %a, f32 %b) {<br>@entry:<br> f32 %as = call $square(%a)<br> f32 %bs = call $square(%b)<br> f32 %sum = add %as, %bs<br> f32 %o = sqrt %sum<br> ret %o<br>}<br><br>function f32 $tri_hypot({f32, f32} %x) {<br> f32 %a = extract %x, 0<br> f32 %b = extract %x, 1<br> f32 %o = call $hypot(%a, %b) // this is a "tail call"<br> ret %o<br>}<br><br>// let's assume that $hypot is used someplace else in the code too</code></pre></code></p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><br>Let’s assume our inlining treshold is 5 operations. Then we would get – Waait there are multiple options…</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h3>Issue 1: (sometimes) multiple options</h3>
|
||||
<p>If we inline the <code><code style="white-space: pre-wrap">$square</code></code> calls, then <code><code style="white-space: pre-wrap">$hypot</code></code> will have too many instructions to be inlined into <code><code style="white-space: pre-wrap">$tri_hypot</code></code>:</p>
|
||||
<p><code><pre><code>...<br>function f32 $hypot(f32 %a, f32 %b) {<br>@entry:<br> // more instructions than our inlining treshold:<br> f32 %ase = add %a, 0<br> f32 %as = add %ase, %a<br> f32 %bse = add %b, 0<br> f32 %bs = add %bse, %b<br> f32 %sum = add %as, %bs<br> f32 %o = sqrt %sum<br> ret %o<br>}<br>...</code></pre></code></p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br>The second option is to inline the <code><code style="white-space: pre-wrap">$hypot</code></code> call into <code><code style="white-space: pre-wrap">$tri_hypot</code></code>. (There are also some other options)</p>
|
||||
<p>Now in this case, it seems obvious to prefer inlining <code><code style="white-space: pre-wrap">$square</code></code> into <code><code style="white-space: pre-wrap">$hypot</code></code>.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h3>Issue 2: ABI requirements on argument passing</h3>
|
||||
<p>If we assume the target ABI only has one f32 register for passing arguments, then we would have to generate additional instructions for passing the second argument of <code><code style="white-space: pre-wrap">$hypot</code></code>, and then it might actually be more efficient to inline <code><code style="white-space: pre-wrap">$hypot</code></code> instead of <code><code style="white-space: pre-wrap">$square</code></code>.</p>
|
||||
<p>This example is not realistic, but this issue actually occurs when compiling lots of code.</p>
|
||||
<p>Another related issue is that having more arguments arranged in a fixed way will require lots of moving data arround at the call site.</p>
|
||||
<p>A solution to this is to make the heuristics not just output code size, but also make it depend on the number of arguments / outputs passed to the function.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h3>Issue 3: (sometimes) prevents optimizations</h3>
|
||||
<p><code><pre><code>function f32 $myfunc(f32 %a, f32 %b) {<br>@entry:<br> f32 %sum = add %a, %b<br> f32 %sq = sqrt %sum<br> ...<br>}<br><br>function $callsite(f32 %a, f32 %b) {<br>@entry:<br> f32 %as = add %a, %a<br> f32 %bs = add %b, %b<br> f32 %x = call $myfunc(%as, %bs)<br> ...<br>}</code></pre></code></p>
|
||||
<p>If the target has a efficient <code><code style="white-space: pre-wrap">hypot</code></code> operation, then that operation will only be used if we inline <code><code style="white-space: pre-wrap">$myfunc</code></code> into <code><code style="white-space: pre-wrap">$callsite</code></code>.</p>
|
||||
<p>This means that inlining is now depended on… instruction selection??</p>
|
||||
<p>This is not the only optimization prevented by not inlining the call. If <code><code style="white-space: pre-wrap">$callsite</code></code> were to be called in a loop, then not inlining would prevent vectorization.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h2>Function outlining</h2>
|
||||
<p>A related optimization is “outlining”. It’s the opposite to inlining. It moves duplicate code into a function, to reduce code size, and sometimes increase performance (because of instruction caching)</p>
|
||||
<p>If we do inlining seperately from outlining, we often get unoptimal code.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h2>A better approach</h2>
|
||||
<p>We can instead first inline <strong>all</strong> inlinable calls, and <strong>then</strong> perform more agressive outlining.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h3>Step 1: inlining</h3>
|
||||
<p>We inline <strong>all</strong> function calls, except for:</p>
|
||||
<ul>
|
||||
<li>self recursion (obviously)</li>
|
||||
<li>functions explicitly marked as no-inline by the user</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h3>Step 2: detect duplicate code</h3>
|
||||
<p>There are many algorithms for doing this.</p>
|
||||
<p>The goal of this step is to both:</p>
|
||||
<ul>
|
||||
<li>maximize size of outlinable section</li>
|
||||
<li>minimize size of code</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h3>Step 3: slightly reduce size of outlinable section</h3>
|
||||
<p>The goal is to reduce size of outlinable sections, to make the code more optimal.</p>
|
||||
<p>This should be ABI and instruction depended, and have the goal of:</p>
|
||||
<ul>
|
||||
<li>reducing argument shuffles required at all call sites</li>
|
||||
<li>reducing register preassure</li>
|
||||
<li>not preventing good isel choices and optimizations.</li>
|
||||
</ul>
|
||||
<p>this is also dependent on the targetted code size.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h3>Step 4: perform outlining</h3>
|
||||
<p>This is obvious.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h3>Issue 1: high compile-time memory usage</h3>
|
||||
<p>Inlining <strong>all</strong> function calls first will increase the memory usage during compilation by A LOT</p>
|
||||
<p>I’m sure that there is a smarter way to implement this method, without actually performing the inlining…</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h2>Conclusion</h2>
|
||||
<p>Function inlining is much more complex than one might think.</p>
|
||||
<p>PS: No idea how to implement this…</p>
|
||||
<p>Subscribe to the <a href="atom.xml">Atom feed</a> to get notified about futre compiler-related articles.</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@@ -1 +0,0 @@
|
||||
build/compiler-inlining.typ.nano.html: common.typ pages/compiler-inlining.typ core-page-style.typ components/header.typ simple-page-layout.typ
|
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
||||
build/compiler-pattern-matching.typ.desktop.html: common.typ pages/compiler-pattern-matching.typ core-page-style.typ components/header.typ simple-page-layout.typ
|
@@ -1 +0,0 @@
|
||||
--input git_rev=34fd6adb3c89bef3f2d18b06b24533b52641bf4a --input git_commit_date="19. August 2025 09:55"
|
@@ -1 +0,0 @@
|
||||
2025-08-19T09:55:17+02:00
|
@@ -1,521 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Approaches to Compiler Pattern Matching</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="icon" sizes="512x512" href="res/favicon.png">
|
||||
<link rel="image_src" type="image/png" href="res/favicon.png">
|
||||
<link type="application/atom+xml" rel="alternate" title="alexs168's blog" href="atom.xml">
|
||||
</head>
|
||||
<body>
|
||||
<style>
|
||||
|
||||
@font-face {
|
||||
font-family: 'DejaVu Sans Mono';
|
||||
src:local('DejaVu Sans Mono'),
|
||||
url('res/DejaVuSansMono.woff2') format('woff2'),
|
||||
local('Courier New'),
|
||||
local(Courier),
|
||||
local(monospace);
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
/*
|
||||
@font-face {
|
||||
font-family: 'DejaVu Sans Mono';
|
||||
src:local('DejaVu Sans Mono'),
|
||||
url('res/DejaVuSansMono-Bold.woff2') format('woff2'),
|
||||
local('Courier New'),
|
||||
local(Courier),
|
||||
local(monospace);
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'DejaVu Sans';
|
||||
src:local('DejaVu Sans'),
|
||||
url('res/DejaVuSans-Bold.woff2') format('woff2'),
|
||||
local('Courier New');
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'DejaVu Sans';
|
||||
src:local('DejaVu Sans'),
|
||||
url('res/DejaVuSans.woff2') format('woff2'),
|
||||
local('Courier New');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}*/
|
||||
|
||||
body {
|
||||
font-family: DejaVu Sans Mono;
|
||||
font-size: 10pt;
|
||||
}
|
||||
|
||||
td {
|
||||
width: 100%;
|
||||
display: inline;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
h1,h2,h3,h4 {
|
||||
margin-top: 1%;
|
||||
margin-bottom: 0.75%;
|
||||
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0.75%;
|
||||
margin-bottom: 0.75%;
|
||||
}
|
||||
|
||||
ul {
|
||||
margin-top: 0%;
|
||||
}
|
||||
|
||||
.current {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
pre {
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #3f51b5;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: #3f51b5;
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h1>Approaches to pattern matching in compilers</h1>
|
||||
<p><span style="font-size: 9pt"><p>Git revision <a href="https://github.com/alex-s168/website/tree/34fd6adb3c89bef3f2d18b06b24533b52641bf4a">#34fd6adb</a></p><p><br>Modified at 19. August 2025 09:55</p><p>Written by <a href="https://alex.vxcc.dev">alex_s168</a></p></span></p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br><span style="text-decoration: underline"><h2>Introduction</h2></span> Compilers often have to deal with pattern matching and rewriting (find-and-replace) inside the compiler IR (intermediate representation).</p>
|
||||
<p>Common use cases for pattern matching in compilers:</p>
|
||||
<ul>
|
||||
<li>“peephole optimizations”: the most common kind of optimization in compilers. They find a short sequence of code and replace it with some other code. For example replacing <span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><code style="white-space: pre-wrap">x <span style="color: #d73a49">&</span> (<span style="color: #b60157">1</span> <span style="color: #d73a49"><<</span> b)</code></span> with a bit test operation.</li>
|
||||
<li>finding a sequence of operations for complex optimization passes to operate on: advanced compilers have complex optimizations that can’t really be performed with simple IR operation replacements, and instead require complex logic. Patterns are used here to find operation sequences where those optimizations are applicable, and also to extract details inside that sequence.</li>
|
||||
<li>code generation: converting the IR to machine code / VM bytecode. A compiler needs to find operations (or sequences of operations) inside the IR, and “replace” them with machine code.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br><span style="text-decoration: underline"><h2>Simplest Approach</h2></span> Currently, most compilers mostly do this inside their source code. For example, in MLIR, most (but not all) pattern matches are performed in C++ code.</p>
|
||||
<p>The only advantage to this approach is that it doesn’t require a complex pattern matching system.</p>
|
||||
<p>I only recommend doing this for small compiler toy projects.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br><span style="text-decoration: underline"><h3>Disadvantages</h3></span> Doing pattern matching this way has many disadvantages.</p>
|
||||
<p><br>Some (but not all):</p>
|
||||
<ul>
|
||||
<li>debugging pattern match rules can be hard</li>
|
||||
<li>IR rewrites need to be tracked manually (for debugging)</li>
|
||||
<li>source locations and debug information also need to be tracked manually, which often isn’t implemented very well.</li>
|
||||
<li>verbose and barely readable pattern matching code</li>
|
||||
<li>overall error-prone</li>
|
||||
</ul>
|
||||
<p>I myself did pattern matching this way in my old compiler backend, and I speak from experience when I say that this approach <strong>sucks</strong> (in most cases).</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br><span style="text-decoration: underline"><h2>Pattern Matching DSLs</h2></span> A custom language for describing IR patterns and IR transformations (aka rewrites).</p>
|
||||
<p>I will put this into the category of “structured pattern matching”.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br>An example is Cranelift’s ISLE DSL:</p>
|
||||
<div class style="margin-top:4pt;"><span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><pre><code><span style="color: #8a8a8a">;;</span><span style="color: #8a8a8a"> x ^ x == 0.</span><br>(<span style="color: #4b69c6">rule</span> (<span style="color: #4b69c6">simplify</span> (<span style="color: #4b69c6">bxor</span> (<span style="color: #4b69c6">ty_int</span> ty) x x))<br> (<span style="color: #4b69c6">subsume</span> (<span style="color: #4b69c6">iconst_u</span> ty <span style="color: #b60157">0</span>)))</code></pre></span></div>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br>Another example is tinygrad’s pattern system:</p>
|
||||
<div class style="margin-top:4pt;"><span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><pre><code>(<span style="color: #4b69c6">UPat</span>(Ops.AND, src<span style="color: #d73a49">=</span>(<br> UPat.<span style="color: #4b69c6">var</span>(<span style="color: #298e0d">"</span><span style="color: #298e0d">x</span><span style="color: #298e0d">"</span>),<br> <span style="color: #4b69c6">UPat</span>(Ops.SHL, src<span style="color: #d73a49">=</span>(<br> UPat.<span style="color: #4b69c6">const</span>(<span style="color: #b60157">1</span>),<br> UPat.<span style="color: #4b69c6">var</span>(<span style="color: #298e0d">"</span><span style="color: #298e0d">b</span><span style="color: #298e0d">"</span>)))),<br> <span style="color: #d73a49">lambda</span> x,b: <span style="color: #4b69c6">UOp</span>(Ops.BIT_TEST, src<span style="color: #d73a49">=</span>(x, b)))</code></pre></span></div>
|
||||
<p>Fun fact: tinygrad actually decompiles the python code inside the second element of the pair, and runs multiple optimization passes on that.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><br>This approach is used by many popular compilers such as LLVM, GCC, and Cranelift for peephole optimizations and code generation.</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br><span style="text-decoration: underline"><h3>Advantages</h3></span></p>
|
||||
<ul>
|
||||
<li><strong>debugging and tracking of rewrites, source locations, and debug information can be done properly</strong></li>
|
||||
<li>patterns themselves can be inspected and modified programmatically.</li>
|
||||
<li>they are easier to use and read than manual pattern matching in the source code.</li>
|
||||
</ul>
|
||||
<p><br>There is however an even better alternative:</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br><span style="text-decoration: underline"><h2>Pattern Matching Dialects</h2></span> I will also put this method into the category of “structured pattern matching”.</p>
|
||||
<p><br>The main example of this is MLIR, with the <span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><code style="white-space: pre-wrap">pdl</code></span> and the <span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><code style="white-space: pre-wrap">transform</code></span> dialects. Sadly few projects/people use these dialects, and instead do pattern matching in C++ code. Probably because the dialects aren’t documented very well.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br><span style="text-decoration: underline"><h3>What are compiler dialects?</h3></span> Modern compilers, especially multi-level compilers, such as MLIR, have their operations grouped in “dialects”.</p>
|
||||
<p>Each dialect either represents specific kinds of operations, like arithmetic operations, or a specific backend’s/frontend’s operations, such as the <span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><code style="white-space: pre-wrap">llvm</code></span>, <span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><code style="white-space: pre-wrap">emitc</code></span>, and the <span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><code style="white-space: pre-wrap">spirv</code></span> dialects in MLIR.</p>
|
||||
<p>Dialects commonly contain operations, data types, as well as optimization and dialect conversion passes.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><br><span style="text-decoration: underline"><h3>Core Concept</h3></span> The IR patterns and transformations are represented using the compiler’s IR. This is mostly done in a separate dialect, with dedicated operations for operating on IR.</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br><span style="text-decoration: underline"><h3>Examples</h3></span> MLIR’s <span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><code style="white-space: pre-wrap">pdl</code></span> dialect can be used to replace <span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><code style="white-space: pre-wrap">arith.addi</code></span> with <span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><code style="white-space: pre-wrap">my.add</code></span> like this:</p>
|
||||
<div class style="margin-top:4pt;"><span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><pre><code>pdl.pattern <span style="color: #d73a49">@replace_addi_with_my_add</span> : benefit(<span style="color: #b60157">1</span>) {<br> <span style="color: #d73a49">%arg0</span> = pdl.operand<br> <span style="color: #d73a49">%arg1</span> = pdl.operand<br> <span style="color: #d73a49">%op</span> = pdl.operation <span style="color: #298e0d">"arith.addi"</span>(<span style="color: #d73a49">%arg0</span>, <span style="color: #d73a49">%arg1</span>)<br><br> pdl.rewrite <span style="color: #d73a49">%op</span> {<br> <span style="color: #d73a49">%new_op</span> = pdl.operation <span style="color: #298e0d">"my.add"</span>(<span style="color: #d73a49">%arg0</span>, <span style="color: #d73a49">%arg1</span>) -> (<span style="color: #d73a49">%op</span>)<br> pdl.replace <span style="color: #d73a49">%op</span> with <span style="color: #d73a49">%new_op</span><br> }<br>}</code></pre></span></div>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br><span style="text-decoration: underline"><h3>Advantages</h3></span></p>
|
||||
<ul>
|
||||
<li>the pattern matching infrastructure can optimize it’s own patterns: The compiler can operate on patterns and rewrite rules like they are normal operations. This removes the need for special infrastructure regarding pattern matching DSLs.</li>
|
||||
<li>the compiler could AOT compile patterns</li>
|
||||
<li>the compiler could optimize, analyze, and combine patterns to reduce compile time.</li>
|
||||
<li>IR (de-)serialization infrastructure in the compiler can also be used to exchange peephole optimizations.</li>
|
||||
<li>bragging rights: your compiler represents its patterns in it’s own IR</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br><span style="text-decoration: underline"><h3>Combining with a DSL</h3></span> I recommend having a pattern matching / rewrite DSL, that transpiles to pattern matching / rewrite dialect operations.</p>
|
||||
<p>The advantage of this over just having a rewrite dialect is that it makes patterns even more readable (and maintainable!)</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br><span style="text-decoration: underline"><h3>E-Graphs</h3></span> <span class style="white-space:nowrap;"><p><a href="https://en.wikipedia.org/wiki/E-graph">E-Graphs</a></p></span> are magical datastructures that can be used to efficiently encode all possible transformations, and then select the best transformation.</p>
|
||||
<p>An example implementation is <a href="https://egraphs-good.github.io/">egg</a></p>
|
||||
<p>Even though E-Graphs solve most problems, I still recommend using a pattern matching dialect, especially in multi-level compilers, to be more flexible, and have more future-proof pattern matching, or you decide that you want to match some complex patterns manually.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br><span style="text-decoration: underline"><h2>More Advantages of Structured Pattern Matching</h2></span></p>
|
||||
<p><span style="text-decoration: underline"><h3>Smart Pattern Matchers</h3></span> Instead of brute-forcing all peephole optimizations (of which there can be a LOT in advanced compilers), the compiler can organize all the patterns to provide more efficient matching. I didn’t yet investigate how to do this. If you have any ideas regarding this, please <a href="https://alex.vxcc.dev">contact me.</a></p>
|
||||
<p>There are other ways to speed up the pattern matching and rewrite process using this too.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><br><span style="text-decoration: underline"><h3>Reversible Transformations</h3></span> I don’t think that there currently is any compiler that does this. If you do know one, again, please <a href="https://alex.vxcc.dev">contact me.</a></div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><br>Optimizing compilers typically deal with code (mostly written by people) that is on a lower level than the compiler theoretically supports. For example, humans tend to write code like this for extracting a bit: <span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><code style="white-space: pre-wrap">x <span style="color: #d73a49">&</span> (<span style="color: #b60157">1</span> <span style="color: #d73a49"><<</span> b)</code></span>, but compilers tend to have a high-level bit test operation (with exceptions). A reason for having higher-level primitives is that it allows the compiler to do more high-level optimizations, but also some target architectures have a bit test operation, that is more optimal.</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br>This is not just the case for “low-level” things like bit tests, but also high level concepts, like a reduction over an array, or even the implementation of a whole algorithm. For example LLVM, since recently, can detect implementations of <a href="https://en.wikipedia.org/wiki/Cyclic_redundancy_check">CRC.</a></p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><br>LLVM actually doesn’t have many dedicated operations like a bit-test operation, and instead canonicalizes all bit-test patterns to <span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><code style="white-space: pre-wrap">x <span style="color: #d73a49">&</span> (<span style="color: #b60157">1</span> <span style="color: #d73a49"><<</span> b) <span style="color: #d73a49">!=</span> <span style="color: #b60157">0</span></code></span>, and matches for that in compiler passes that expect bit test operations.</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><br>Now let’s go back to the <span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><code style="white-space: pre-wrap">x <span style="color: #d73a49">&</span> (<span style="color: #b60157">1</span> <span style="color: #d73a49"><<</span> b)</code></span> (bit test) example. Optimizing compilers should be able to detect that, and other bit test patterns (like <span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><code style="white-space: pre-wrap">x <span style="color: #d73a49">&</span> (<span style="color: #b60157">1</span> <span style="color: #d73a49"><<</span> b) <span style="color: #d73a49">></span> <span style="color: #b60157">0</span></code></span>), and then replace those with a bit-test operation. But they also have to be able to convert bit-test operations back to their implementation for compilation targets that don’t have a bit-test instruction. Currently, compiler backends do this by having separate patterns for converting bit-test to it’s dedicated operation, and back.</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br>A better solution is to associate a set of implementations with the bit test operation, and make the compiler <strong>automatically reverse</strong> those to generate the best implementation (in the instruction selector for example).</p>
|
||||
<p>Implementing pattern/transformation reversion can be challenging however, but it provides many benefits, and all “big” compilers should definitely do this, in my opinion.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br><span style="text-decoration: underline"><h3>Runtime Library</h3></span> Compilers typically come with a runtime library that implement more complex operations that aren’t supported by most processors or architectures.</p>
|
||||
<p>The implementation of those functions should also use that pattern matching dialect. This allows your backend to detect code written by users with a similar implementation as in the runtime library, giving you some additional optimizations for free.</p>
|
||||
<p>I don’t think any compiler currently does this either.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br><span style="text-decoration: underline"><h2>Problems with Pattern Matching</h2></span> The main problem is ordering the patterns.</p>
|
||||
<p>As an example, consider these three patterns:</p>
|
||||
<div class style="margin-top:4pt;"><span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><pre><code><span style="color: #8a8a8a">;;</span><span style="color: #8a8a8a"> A</span><br>(<span style="color: #4b69c6">add</span> x:Const y) => (<span style="color: #4b69c6">add</span> y x)<br><br><span style="color: #8a8a8a">;;</span><span style="color: #8a8a8a"> B</span><br>(<span style="color: #4b69c6">sub</span> (<span style="color: #4b69c6">add</span> x y:Const) z:Const) => (<span style="color: #4b69c6">lea</span> x y (<span style="color: #4b69c6">const_neg</span> z))<br><br><span style="color: #8a8a8a">;;</span><span style="color: #8a8a8a"> C</span><br>(<span style="color: #4b69c6">add</span> x <span style="color: #b60157">1</span>) => (<span style="color: #4b69c6">inc</span> x)</code></pre></span></div>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br>Now what should the compiler do when it sees this:</p>
|
||||
<div class style="margin-top:4pt;"><span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><pre><code>(<span style="color: #4b69c6">sub</span> (<span style="color: #4b69c6">add</span> <span style="color: #b60157">5</span> <span style="color: #b60157">1</span>) <span style="color: #b60157">2</span>)</code></pre></span></div>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br>All three patterns would match:</p>
|
||||
<div class style="margin-top:4pt;"><span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><pre><code><span style="color: #8a8a8a">;;</span><span style="color: #8a8a8a"> apply A</span><br>(<span style="color: #4b69c6">sub</span> (<span style="color: #4b69c6">add</span> <span style="color: #b60157">5</span> <span style="color: #b60157">1</span>) <span style="color: #b60157">2</span>) => (<span style="color: #4b69c6">sub</span> (<span style="color: #4b69c6">add</span> <span style="color: #b60157">1</span> <span style="color: #b60157">5</span>) <span style="color: #b60157">2</span>)<br><span style="color: #8a8a8a">;;</span><span style="color: #8a8a8a"> only B applies now</span><br>(<span style="color: #4b69c6">sub</span> (<span style="color: #4b69c6">add</span> <span style="color: #b60157">1</span> <span style="color: #b60157">5</span>) <span style="color: #b60157">2</span>) => (<span style="color: #4b69c6">lea</span> <span style="color: #b60157">1</span> <span style="color: #b60157">5</span> (<span style="color: #4b69c6">const_neg</span> <span style="color: #b60157">2</span>))<br><span style="color: #8a8a8a">;;</span><span style="color: #8a8a8a"> nothing applies anymore</span><br><br><span style="color: #8a8a8a">;;</span><span style="color: #8a8a8a"> alternatively apply B</span><br>(<span style="color: #4b69c6">sub</span> (<span style="color: #4b69c6">add</span> <span style="color: #b60157">5</span> <span style="color: #b60157">1</span>) <span style="color: #b60157">2</span>) => (<span style="color: #4b69c6">lea</span> <span style="color: #b60157">5</span> <span style="color: #b60157">1</span> (<span style="color: #4b69c6">const_neg</span> <span style="color: #b60157">2</span>))<br><span style="color: #8a8a8a">;;</span><span style="color: #8a8a8a"> nothing applies anymore</span><br><br><span style="color: #8a8a8a">;;</span><span style="color: #8a8a8a"> atlernatively apply C</span><br>(<span style="color: #4b69c6">sub</span> (<span style="color: #4b69c6">add</span> <span style="color: #b60157">5</span> <span style="color: #b60157">1</span>) <span style="color: #b60157">2</span>) => (<span style="color: #4b69c6">sub</span> (<span style="color: #4b69c6">inc</span> <span style="color: #b60157">5</span>) <span style="color: #b60157">2</span>)<br><span style="color: #8a8a8a">;;</span><span style="color: #8a8a8a"> nothing applies anymore</span></code></pre></span></div>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br>Now which of those transformations should be performed?</p>
|
||||
<p>This is not as easy to solve as it seems, especially in the context of instruction selection (specifically scheduling), where the performance on processors depends on a sequence of instructions, instead of just a single instruction.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br><span style="text-decoration: underline"><h3>Superscalar CPUs</h3></span> Modern processor architecture features like superscalar execution make this even more complicated.</p>
|
||||
<p><br>As a simple, <strong>unrealistic</strong> example, let’s imagine a CPU (core) that has one bit operations execution unit, and two ALU execution units / ports.<br>This means that the CPU can execute two instructions in the ALU unit and one instruction in the bit ops unit at the same time.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br>One might think that always optimizing <span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><code style="white-space: pre-wrap">a & (1 << b)</code></span> to a bit test operation is good for performance. But in this example, that is not the case.</p>
|
||||
<p>If we have a function that does a lot of bitwise operations next to each other, and the compiler replaces all bit tests with bit test operations, suddenly all operations depend on the bit ops unit, which means that instead of executing 3 instructions at a time (ignoring pipelining), the CPU can only execute one instruction at a time.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br>This shows that we won’t know if an optimization is actually good, until we are at a late point in the compilation process where we can simulate the CPU’s instruction scheduling.</p>
|
||||
<p>This does not only apply to instruction selection, but also to more higher-level optimizations, such as loop and control flow related optimizations.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br><span style="text-decoration: underline"><h2>Conclusion</h2></span> One can see how pattern matching dialects are the best option to approach pattern matching.</p>
|
||||
<p><br>Someone wanted me to insert a takeaway here, but I won’t.</p>
|
||||
<p><br>PS: I’ll hunt down everyone who still decides to do pattern matching in their compiler source after reading this article.</p>
|
||||
</div>
|
||||
<script>
|
||||
|
||||
function gotoVariant(variant) {
|
||||
window.location.href = window.location.href.replace(/\.\w+.html/g, variant);
|
||||
}
|
||||
|
||||
window.addEventListener('beforeprint', (event) => {
|
||||
gotoVariant('.min.pdf');
|
||||
});
|
||||
|
||||
</script>
|
||||
<script src="coffee.js" async>
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@@ -1 +0,0 @@
|
||||
build/compiler-pattern-matching.typ.min.html: common.typ pages/compiler-pattern-matching.typ core-page-style.typ components/header.typ simple-page-layout.typ
|
@@ -1 +0,0 @@
|
||||
build/compiler-pattern-matching.typ.min.pdf: common.typ pages/compiler-pattern-matching.typ core-page-style.typ components/header.typ simple-page-layout.typ
|
@@ -1,347 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Approaches to Compiler Pattern Matching</title>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h1>Approaches to pattern matching in compilers</h1>
|
||||
<p><span style="font-size: 9pt"><p>Last modified: 19. August 2025 09:55 (Git #<code><code style="white-space: pre-wrap">34fd6adb</code></code>)</p><p>Written by <a href="https://alex.vxcc.dev">alex_s168</a></p></span></p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h2>Introduction</h2>
|
||||
<p>Compilers often have to deal with pattern matching and rewriting (find-and-replace) inside the compiler IR (intermediate representation).</p>
|
||||
<p>Common use cases for pattern matching in compilers:</p>
|
||||
<ul>
|
||||
<li>“peephole optimizations”: the most common kind of optimization in compilers. They find a short sequence of code and replace it with some other code. For example replacing <code><code style="white-space: pre-wrap">x <span style="color: #d73a49">&</span> (<span style="color: #b60157">1</span> <span style="color: #d73a49"><<</span> b)</code></code> with a bit test operation.</li>
|
||||
<li>finding a sequence of operations for complex optimization passes to operate on: advanced compilers have complex optimizations that can’t really be performed with simple IR operation replacements, and instead require complex logic. Patterns are used here to find operation sequences where those optimizations are applicable, and also to extract details inside that sequence.</li>
|
||||
<li>code generation: converting the IR to machine code / VM bytecode. A compiler needs to find operations (or sequences of operations) inside the IR, and “replace” them with machine code.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h2>Simplest Approach</h2>
|
||||
<p>Currently, most compilers mostly do this inside their source code. For example, in MLIR, most (but not all) pattern matches are performed in C++ code.</p>
|
||||
<p>The only advantage to this approach is that it doesn’t require a complex pattern matching system.</p>
|
||||
<p>I only recommend doing this for small compiler toy projects.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h3>Disadvantages</h3>
|
||||
<p>Doing pattern matching this way has many disadvantages.</p>
|
||||
<p><br>Some (but not all):</p>
|
||||
<ul>
|
||||
<li>debugging pattern match rules can be hard</li>
|
||||
<li>IR rewrites need to be tracked manually (for debugging)</li>
|
||||
<li>source locations and debug information also need to be tracked manually, which often isn’t implemented very well.</li>
|
||||
<li>verbose and barely readable pattern matching code</li>
|
||||
<li>overall error-prone</li>
|
||||
</ul>
|
||||
<p>I myself did pattern matching this way in my old compiler backend, and I speak from experience when I say that this approach <strong>sucks</strong> (in most cases).</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h2>Pattern Matching DSLs</h2>
|
||||
<p>A custom language for describing IR patterns and IR transformations (aka rewrites).</p>
|
||||
<p>I will put this into the category of “structured pattern matching”.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br>An example is Cranelift’s ISLE DSL:</p>
|
||||
<p><code><pre><code><span style="color: #8a8a8a">;;</span><span style="color: #8a8a8a"> x ^ x == 0.</span><br>(<span style="color: #4b69c6">rule</span> (<span style="color: #4b69c6">simplify</span> (<span style="color: #4b69c6">bxor</span> (<span style="color: #4b69c6">ty_int</span> ty) x x))<br> (<span style="color: #4b69c6">subsume</span> (<span style="color: #4b69c6">iconst_u</span> ty <span style="color: #b60157">0</span>)))</code></pre></code></p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br>Another example is tinygrad’s pattern system:</p>
|
||||
<p><code><pre><code>(<span style="color: #4b69c6">UPat</span>(Ops.AND, src<span style="color: #d73a49">=</span>(<br> UPat.<span style="color: #4b69c6">var</span>(<span style="color: #298e0d">"</span><span style="color: #298e0d">x</span><span style="color: #298e0d">"</span>),<br> <span style="color: #4b69c6">UPat</span>(Ops.SHL, src<span style="color: #d73a49">=</span>(<br> UPat.<span style="color: #4b69c6">const</span>(<span style="color: #b60157">1</span>),<br> UPat.<span style="color: #4b69c6">var</span>(<span style="color: #298e0d">"</span><span style="color: #298e0d">b</span><span style="color: #298e0d">"</span>)))),<br> <span style="color: #d73a49">lambda</span> x,b: <span style="color: #4b69c6">UOp</span>(Ops.BIT_TEST, src<span style="color: #d73a49">=</span>(x, b)))</code></pre></code></p>
|
||||
<p>Fun fact: tinygrad actually decompiles the python code inside the second element of the pair, and runs multiple optimization passes on that.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><br>This approach is used by many popular compilers such as LLVM, GCC, and Cranelift for peephole optimizations and code generation.</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h3>Advantages</h3>
|
||||
<ul>
|
||||
<li><strong>debugging and tracking of rewrites, source locations, and debug information can be done properly</strong></li>
|
||||
<li>patterns themselves can be inspected and modified programmatically.</li>
|
||||
<li>they are easier to use and read than manual pattern matching in the source code.</li>
|
||||
</ul>
|
||||
<p><br>There is however an even better alternative:</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h2>Pattern Matching Dialects</h2>
|
||||
<p>I will also put this method into the category of “structured pattern matching”.</p>
|
||||
<p><br>The main example of this is MLIR, with the <code><code style="white-space: pre-wrap">pdl</code></code> and the <code><code style="white-space: pre-wrap">transform</code></code> dialects. Sadly few projects/people use these dialects, and instead do pattern matching in C++ code. Probably because the dialects aren’t documented very well.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h3>What are compiler dialects?</h3>
|
||||
<p>Modern compilers, especially multi-level compilers, such as MLIR, have their operations grouped in “dialects”.</p>
|
||||
<p>Each dialect either represents specific kinds of operations, like arithmetic operations, or a specific backend’s/frontend’s operations, such as the <code><code style="white-space: pre-wrap">llvm</code></code>, <code><code style="white-space: pre-wrap">emitc</code></code>, and the <code><code style="white-space: pre-wrap">spirv</code></code> dialects in MLIR.</p>
|
||||
<p>Dialects commonly contain operations, data types, as well as optimization and dialect conversion passes.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h3>Core Concept</h3>
|
||||
<p>The IR patterns and transformations are represented using the compiler’s IR. This is mostly done in a separate dialect, with dedicated operations for operating on IR.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h3>Examples</h3>
|
||||
<p>MLIR’s <code><code style="white-space: pre-wrap">pdl</code></code> dialect can be used to replace <code><code style="white-space: pre-wrap">arith.addi</code></code> with <code><code style="white-space: pre-wrap">my.add</code></code> like this:</p>
|
||||
<p><code><pre><code>pdl.pattern <span style="color: #d73a49">@replace_addi_with_my_add</span> : benefit(<span style="color: #b60157">1</span>) {<br> <span style="color: #d73a49">%arg0</span> = pdl.operand<br> <span style="color: #d73a49">%arg1</span> = pdl.operand<br> <span style="color: #d73a49">%op</span> = pdl.operation <span style="color: #298e0d">"arith.addi"</span>(<span style="color: #d73a49">%arg0</span>, <span style="color: #d73a49">%arg1</span>)<br><br> pdl.rewrite <span style="color: #d73a49">%op</span> {<br> <span style="color: #d73a49">%new_op</span> = pdl.operation <span style="color: #298e0d">"my.add"</span>(<span style="color: #d73a49">%arg0</span>, <span style="color: #d73a49">%arg1</span>) -> (<span style="color: #d73a49">%op</span>)<br> pdl.replace <span style="color: #d73a49">%op</span> with <span style="color: #d73a49">%new_op</span><br> }<br>}</code></pre></code></p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h3>Advantages</h3>
|
||||
<ul>
|
||||
<li>the pattern matching infrastructure can optimize it’s own patterns: The compiler can operate on patterns and rewrite rules like they are normal operations. This removes the need for special infrastructure regarding pattern matching DSLs.</li>
|
||||
<li>the compiler could AOT compile patterns</li>
|
||||
<li>the compiler could optimize, analyze, and combine patterns to reduce compile time.</li>
|
||||
<li>IR (de-)serialization infrastructure in the compiler can also be used to exchange peephole optimizations.</li>
|
||||
<li>bragging rights: your compiler represents its patterns in it’s own IR</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h3>Combining with a DSL</h3>
|
||||
<p>I recommend having a pattern matching / rewrite DSL, that transpiles to pattern matching / rewrite dialect operations.</p>
|
||||
<p>The advantage of this over just having a rewrite dialect is that it makes patterns even more readable (and maintainable!)</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h3>E-Graphs</h3>
|
||||
<p><span class style="white-space:nowrap;"><a href="https://en.wikipedia.org/wiki/E-graph">E-Graphs</a></span> are magical datastructures that can be used to efficiently encode all possible transformations, and then select the best transformation.</p>
|
||||
<p>An example implementation is <a href="https://egraphs-good.github.io/">egg</a></p>
|
||||
<p>Even though E-Graphs solve most problems, I still recommend using a pattern matching dialect, especially in multi-level compilers, to be more flexible, and have more future-proof pattern matching, or you decide that you want to match some complex patterns manually.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h2>More Advantages of Structured Pattern Matching</h2>
|
||||
<h3>Smart Pattern Matchers</h3>
|
||||
<p>Instead of brute-forcing all peephole optimizations (of which there can be a LOT in advanced compilers), the compiler can organize all the patterns to provide more efficient matching. I didn’t yet investigate how to do this. If you have any ideas regarding this, please <a href="https://alex.vxcc.dev">contact me.</a></p>
|
||||
<p>There are other ways to speed up the pattern matching and rewrite process using this too.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h3>Reversible Transformations</h3>
|
||||
<p>I don’t think that there currently is any compiler that does this. If you do know one, again, please <a href="https://alex.vxcc.dev">contact me.</a></p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><br>Optimizing compilers typically deal with code (mostly written by people) that is on a lower level than the compiler theoretically supports. For example, humans tend to write code like this for extracting a bit: <code><code style="white-space: pre-wrap">x <span style="color: #d73a49">&</span> (<span style="color: #b60157">1</span> <span style="color: #d73a49"><<</span> b)</code></code>, but compilers tend to have a high-level bit test operation (with exceptions). A reason for having higher-level primitives is that it allows the compiler to do more high-level optimizations, but also some target architectures have a bit test operation, that is more optimal.</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><br>This is not just the case for “low-level” things like bit tests, but also high level concepts, like a reduction over an array, or even the implementation of a whole algorithm. For example LLVM, since recently, can detect implementations of <a href="https://en.wikipedia.org/wiki/Cyclic_redundancy_check">CRC.</a></div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><br>LLVM actually doesn’t have many dedicated operations like a bit-test operation, and instead canonicalizes all bit-test patterns to <code><code style="white-space: pre-wrap">x <span style="color: #d73a49">&</span> (<span style="color: #b60157">1</span> <span style="color: #d73a49"><<</span> b) <span style="color: #d73a49">!=</span> <span style="color: #b60157">0</span></code></code>, and matches for that in compiler passes that expect bit test operations.</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><br>Now let’s go back to the <code><code style="white-space: pre-wrap">x <span style="color: #d73a49">&</span> (<span style="color: #b60157">1</span> <span style="color: #d73a49"><<</span> b)</code></code> (bit test) example. Optimizing compilers should be able to detect that, and other bit test patterns (like <code><code style="white-space: pre-wrap">x <span style="color: #d73a49">&</span> (<span style="color: #b60157">1</span> <span style="color: #d73a49"><<</span> b) <span style="color: #d73a49">></span> <span style="color: #b60157">0</span></code></code>), and then replace those with a bit-test operation. But they also have to be able to convert bit-test operations back to their implementation for compilation targets that don’t have a bit-test instruction. Currently, compiler backends do this by having separate patterns for converting bit-test to it’s dedicated operation, and back.</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br>A better solution is to associate a set of implementations with the bit test operation, and make the compiler <strong>automatically reverse</strong> those to generate the best implementation (in the instruction selector for example).</p>
|
||||
<p>Implementing pattern/transformation reversion can be challenging however, but it provides many benefits, and all “big” compilers should definitely do this, in my opinion.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h3>Runtime Library</h3>
|
||||
<p>Compilers typically come with a runtime library that implement more complex operations that aren’t supported by most processors or architectures.</p>
|
||||
<p>The implementation of those functions should also use that pattern matching dialect. This allows your backend to detect code written by users with a similar implementation as in the runtime library, giving you some additional optimizations for free.</p>
|
||||
<p>I don’t think any compiler currently does this either.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h2>Problems with Pattern Matching</h2>
|
||||
<p>The main problem is ordering the patterns.</p>
|
||||
<p>As an example, consider these three patterns:</p>
|
||||
<p><code><pre><code><span style="color: #8a8a8a">;;</span><span style="color: #8a8a8a"> A</span><br>(<span style="color: #4b69c6">add</span> x:Const y) => (<span style="color: #4b69c6">add</span> y x)<br><br><span style="color: #8a8a8a">;;</span><span style="color: #8a8a8a"> B</span><br>(<span style="color: #4b69c6">sub</span> (<span style="color: #4b69c6">add</span> x y:Const) z:Const) => (<span style="color: #4b69c6">lea</span> x y (<span style="color: #4b69c6">const_neg</span> z))<br><br><span style="color: #8a8a8a">;;</span><span style="color: #8a8a8a"> C</span><br>(<span style="color: #4b69c6">add</span> x <span style="color: #b60157">1</span>) => (<span style="color: #4b69c6">inc</span> x)</code></pre></code></p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br>Now what should the compiler do when it sees this:</p>
|
||||
<p><code><pre><code>(<span style="color: #4b69c6">sub</span> (<span style="color: #4b69c6">add</span> <span style="color: #b60157">5</span> <span style="color: #b60157">1</span>) <span style="color: #b60157">2</span>)</code></pre></code></p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br>All three patterns would match:</p>
|
||||
<p><code><pre><code><span style="color: #8a8a8a">;;</span><span style="color: #8a8a8a"> apply A</span><br>(<span style="color: #4b69c6">sub</span> (<span style="color: #4b69c6">add</span> <span style="color: #b60157">5</span> <span style="color: #b60157">1</span>) <span style="color: #b60157">2</span>) => (<span style="color: #4b69c6">sub</span> (<span style="color: #4b69c6">add</span> <span style="color: #b60157">1</span> <span style="color: #b60157">5</span>) <span style="color: #b60157">2</span>)<br><span style="color: #8a8a8a">;;</span><span style="color: #8a8a8a"> only B applies now</span><br>(<span style="color: #4b69c6">sub</span> (<span style="color: #4b69c6">add</span> <span style="color: #b60157">1</span> <span style="color: #b60157">5</span>) <span style="color: #b60157">2</span>) => (<span style="color: #4b69c6">lea</span> <span style="color: #b60157">1</span> <span style="color: #b60157">5</span> (<span style="color: #4b69c6">const_neg</span> <span style="color: #b60157">2</span>))<br><span style="color: #8a8a8a">;;</span><span style="color: #8a8a8a"> nothing applies anymore</span><br><br><span style="color: #8a8a8a">;;</span><span style="color: #8a8a8a"> alternatively apply B</span><br>(<span style="color: #4b69c6">sub</span> (<span style="color: #4b69c6">add</span> <span style="color: #b60157">5</span> <span style="color: #b60157">1</span>) <span style="color: #b60157">2</span>) => (<span style="color: #4b69c6">lea</span> <span style="color: #b60157">5</span> <span style="color: #b60157">1</span> (<span style="color: #4b69c6">const_neg</span> <span style="color: #b60157">2</span>))<br><span style="color: #8a8a8a">;;</span><span style="color: #8a8a8a"> nothing applies anymore</span><br><br><span style="color: #8a8a8a">;;</span><span style="color: #8a8a8a"> atlernatively apply C</span><br>(<span style="color: #4b69c6">sub</span> (<span style="color: #4b69c6">add</span> <span style="color: #b60157">5</span> <span style="color: #b60157">1</span>) <span style="color: #b60157">2</span>) => (<span style="color: #4b69c6">sub</span> (<span style="color: #4b69c6">inc</span> <span style="color: #b60157">5</span>) <span style="color: #b60157">2</span>)<br><span style="color: #8a8a8a">;;</span><span style="color: #8a8a8a"> nothing applies anymore</span></code></pre></code></p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br>Now which of those transformations should be performed?</p>
|
||||
<p>This is not as easy to solve as it seems, especially in the context of instruction selection (specifically scheduling), where the performance on processors depends on a sequence of instructions, instead of just a single instruction.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h3>Superscalar CPUs</h3>
|
||||
<p>Modern processor architecture features like superscalar execution make this even more complicated.</p>
|
||||
<p><br>As a simple, <strong>unrealistic</strong> example, let’s imagine a CPU (core) that has one bit operations execution unit, and two ALU execution units / ports.<br>This means that the CPU can execute two instructions in the ALU unit and one instruction in the bit ops unit at the same time.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br>One might think that always optimizing <code><code style="white-space: pre-wrap">a & (1 << b)</code></code> to a bit test operation is good for performance. But in this example, that is not the case.</p>
|
||||
<p>If we have a function that does a lot of bitwise operations next to each other, and the compiler replaces all bit tests with bit test operations, suddenly all operations depend on the bit ops unit, which means that instead of executing 3 instructions at a time (ignoring pipelining), the CPU can only execute one instruction at a time.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br>This shows that we won’t know if an optimization is actually good, until we are at a late point in the compilation process where we can simulate the CPU’s instruction scheduling.</p>
|
||||
<p>This does not only apply to instruction selection, but also to more higher-level optimizations, such as loop and control flow related optimizations.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h2>Conclusion</h2>
|
||||
<p>One can see how pattern matching dialects are the best option to approach pattern matching.</p>
|
||||
<p><br>Someone wanted me to insert a takeaway here, but I won’t.</p>
|
||||
<p><br>PS: I’ll hunt down everyone who still decides to do pattern matching in their compiler source after reading this article.</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@@ -1 +0,0 @@
|
||||
build/compiler-pattern-matching.typ.nano.html: common.typ pages/compiler-pattern-matching.typ core-page-style.typ components/header.typ simple-page-layout.typ
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1 +0,0 @@
|
||||
a9fff3f8a90554daae5f56a4727ba8b592dc5774
|
@@ -1,185 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Alexander Nutz</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="icon" sizes="512x512" href="res/favicon.png">
|
||||
<link rel="image_src" type="image/png" href="res/favicon.png">
|
||||
<link type="application/atom+xml" rel="alternate" title="alexs168's blog" href="atom.xml">
|
||||
</head>
|
||||
<body>
|
||||
<style>
|
||||
|
||||
@font-face {
|
||||
font-family: 'DejaVu Sans Mono';
|
||||
src:local('DejaVu Sans Mono'),
|
||||
url('res/DejaVuSansMono.woff2') format('woff2'),
|
||||
local('Courier New'),
|
||||
local(Courier),
|
||||
local(monospace);
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
/*
|
||||
@font-face {
|
||||
font-family: 'DejaVu Sans Mono';
|
||||
src:local('DejaVu Sans Mono'),
|
||||
url('res/DejaVuSansMono-Bold.woff2') format('woff2'),
|
||||
local('Courier New'),
|
||||
local(Courier),
|
||||
local(monospace);
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'DejaVu Sans';
|
||||
src:local('DejaVu Sans'),
|
||||
url('res/DejaVuSans-Bold.woff2') format('woff2'),
|
||||
local('Courier New');
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'DejaVu Sans';
|
||||
src:local('DejaVu Sans'),
|
||||
url('res/DejaVuSans.woff2') format('woff2'),
|
||||
local('Courier New');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}*/
|
||||
|
||||
body {
|
||||
font-family: DejaVu Sans Mono;
|
||||
font-size: 17pt;
|
||||
}
|
||||
|
||||
td {
|
||||
width: 100%;
|
||||
display: inline;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
h1,h2,h3,h4 {
|
||||
margin-top: 1%;
|
||||
margin-bottom: 0.75%;
|
||||
margin-left: -0.75%;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0.75%;
|
||||
margin-bottom: 0.75%;
|
||||
}
|
||||
|
||||
ul {
|
||||
margin-top: 0%;
|
||||
}
|
||||
|
||||
.current {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
pre {
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #3f51b5;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: #3f51b5;
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
<table>
|
||||
<tr>
|
||||
<td><span class="sidebar" style><span class="column-fixed" style="display: inline-flex; position: fixed; justify-content: center; width: 25%"><table><tr><td></td></tr><tr><td></td></tr><tr><td></td></tr><tr><td></td></tr><tr><td><style>
|
||||
@media only screen and (max-width: 1200px) {
|
||||
.sidebar {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.column-fixed {
|
||||
width: 0% !important;
|
||||
}
|
||||
|
||||
.body-column {
|
||||
left: 3% !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1800px) {
|
||||
.body-column > span {
|
||||
width: 75% !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1200px) {
|
||||
.body-column {
|
||||
width: 97% !important;
|
||||
}
|
||||
.body-column > span {
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
|
||||
.hide { display: inline; background: black; transition: background 0.3s linear; }
|
||||
.hide:hover, .hide:focus { background: transparent; }
|
||||
</style></td></tr></table><style>
|
||||
.column-fixed > table > tbody > tr > td > * { width: 100%; }
|
||||
</style></span></span></td>
|
||||
<td><span class="body-column" style="position: absolute; left: 28%; width: 72%"><span style="
|
||||
|
||||
|
||||
width:50%;
|
||||
|
||||
display:inline-block"><p><br>
|
||||
</p><h1>alex_s168</h1><p><br>
|
||||
</p><p>Articles (<a href="atom.xml">Atom feed</a>) <br>
|
||||
</p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;"><a href="compiler-inlining.typ.desktop.html">Automatically inlining functions is not easy</a></span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;"><a href="compiler-pattern-matching.typ.desktop.html">Approaches to pattern matching in compilers</a></span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;"><a href="article-favicon.typ.desktop.html">The making of the favicon</a></span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">└─</span> <span class style="flex:1;"><a href="article-make-regex-engine-1.typ.desktop.html">Making a simple RegEx engine:
|
||||
Part 1: Introduction to RegEx</a></span></span></p><p><br>
|
||||
</p><p>Socials <br>
|
||||
</p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;"><a href="https://github.com/alex-s168">GitHub</a></span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;">Discord: alex_s168</span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;"><a href="mailto:alexandernutz68@gmail.com">E-Mail</a></span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;"><a href="https://njump.me/npub17semnd065ahhsajlylkyd3lahcykpuw45rhj7cge3uqdfq24y84st0g4gr">nostr</a></span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">└─</span> <span class style="flex:1;"><a href="https://codeberg.org/alex-s168">Codeberg</a></span></span></p><p><br>
|
||||
</p><p>Noteable projects <br>
|
||||
</p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;">Programming languages and compilers</span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">| ├─</span> <span class style="flex:1;"><a href="https://github.com/vxcc-backend/vxcc-new">vxcc</a>: WiP multi-level compiler</span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">| ├─</span> <span class style="flex:1;"><a href="https://github.com/alex-s168/uiuac">uiuac</a>: (discontinued) Optimizing compiler for the <a href="https://uiua.org">Uiua programming language</a></span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">| ├─</span> <span class style="flex:1;"><a href="https://github.com/Lambda-Mountain-Compiler-Backend/lambda-mountain">LSTS’s standard library</a></span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">| ├─</span> <span class style="flex:1;">FP programming language compiler mostly using <a href="https://en.wikipedia.org/wiki/Interaction_nets">interaction nets</a></span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">| └─</span> <span class style="flex:1;"><a href="https://github.com/alex-s168/lil-rs">lil-rs</a>: WiP implementation of <a href="http://beyondloom.com/decker/lil.html">lil</a></span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;">Misc.</span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">| ├─</span> <span class style="flex:1;"><a href="https://github.com/alex-s168/tpre">tpre</a>: Fast and minimal RegEx engine</span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">| └─</span> <span class style="flex:1;">nostr relay implementation</span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;">PCBs</span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">| └─</span> <span class style="flex:1;"><a href="project-etc-nand.typ.desktop.html">etc-nand</a>: <a href="https://github.com/ETC-A/etca-spec/">ETC.A</a> CPU from NAND gates</span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">└─</span> <span class style="flex:1;">FPGA designs</span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;"> ├─</span> <span class style="flex:1;">RMII MAC in <a href="https://www.chisel-lang.org/">Chisel</a></span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;"> └─</span> <span class style="flex:1;">Configurable AES accelerator in <a href="https://www.chisel-lang.org/">Chisel</a></span></span></p><p><br>
|
||||
Skills <br>
|
||||
</p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;">Programming languages</span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">| ├─</span> <span class style="flex:1;">C++ and C</span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">| ├─</span> <span class style="flex:1;">Rust</span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">| ├─</span> <span class style="flex:1;"><a href="https://uiua.org">Uiua</a></span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">| └─</span> <span class style="flex:1;">Python, Lua, …</span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;">Writing compiler frontends but mostly backends</span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;">Hardware design with <a href="https://www.chisel-lang.org/">Chisel</a> and Verilog</span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">└─</span> <span class style="flex:1;">Internals of MLIR</span></span></p><p><br>
|
||||
<br>
|
||||
This website is written almost entirely in <a href="https://typst.app/docs">typst</a>.</p><p><a href="https://github.com/alex-s168/website">Website source code</a></p><p><br>
|
||||
<br>
|
||||
Latest version of my badge:<br><span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><code style="white-space: pre-wrap">https://alex.vxcc.dev/res/badge.png</code></span></p><p><br>
|
||||
Check out these websites:<br><a href="https://alex.vxcc.dev" target="_blank"><img src="res/badges/alex" alt="link to alex_s168" attributionsrc="https://alex.vxcc.dev/res/badge.png" fetchpriority="low" style="padding-left:10px; padding-right:14px" width="114.4" height="40.300000000000004"></a><a href="https://512b.dev/ote/" target="_blank"><img src="res/badges/ote" alt="link to otesunki" attributionsrc="https://512b.dev/assets/lagtrain.gif" fetchpriority="low" style="padding-left:10px; padding-right:14px" width="114.4" height="40.300000000000004"></a><a href="https://512b.dev/syn/" target="_blank"><img src="res/badges/syn" alt="link to syn" attributionsrc="https://512b.dev/syn/badge.png" fetchpriority="low" style="padding-left:10px; padding-right:14px" width="114.4" height="40.300000000000004"></a></p></span></span></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
<script>
|
||||
|
||||
function gotoVariant(variant) {
|
||||
window.location.href = window.location.href.replace(/\.\w+.html/g, variant);
|
||||
}
|
||||
|
||||
window.addEventListener('beforeprint', (event) => {
|
||||
gotoVariant('.min.pdf');
|
||||
});
|
||||
|
||||
</script>
|
||||
<script src="coffee.js" async>
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@@ -1 +0,0 @@
|
||||
build/index.typ.desktop.html: common.typ pages/index.typ core-page-style.typ build/pages.typ simple-page-layout.typ
|
@@ -1 +0,0 @@
|
||||
--input git_rev=a9fff3f8a90554daae5f56a4727ba8b592dc5774 --input git_commit_date="26. August 2025 21:15"
|
@@ -1 +0,0 @@
|
||||
2025-08-26T21:15:58+02:00
|
@@ -1,183 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Alexander Nutz</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="icon" sizes="512x512" href="res/favicon.png">
|
||||
<link rel="image_src" type="image/png" href="res/favicon.png">
|
||||
<link type="application/atom+xml" rel="alternate" title="alexs168's blog" href="atom.xml">
|
||||
</head>
|
||||
<body>
|
||||
<style>
|
||||
|
||||
@font-face {
|
||||
font-family: 'DejaVu Sans Mono';
|
||||
src:local('DejaVu Sans Mono'),
|
||||
url('res/DejaVuSansMono.woff2') format('woff2'),
|
||||
local('Courier New'),
|
||||
local(Courier),
|
||||
local(monospace);
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
/*
|
||||
@font-face {
|
||||
font-family: 'DejaVu Sans Mono';
|
||||
src:local('DejaVu Sans Mono'),
|
||||
url('res/DejaVuSansMono-Bold.woff2') format('woff2'),
|
||||
local('Courier New'),
|
||||
local(Courier),
|
||||
local(monospace);
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'DejaVu Sans';
|
||||
src:local('DejaVu Sans'),
|
||||
url('res/DejaVuSans-Bold.woff2') format('woff2'),
|
||||
local('Courier New');
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'DejaVu Sans';
|
||||
src:local('DejaVu Sans'),
|
||||
url('res/DejaVuSans.woff2') format('woff2'),
|
||||
local('Courier New');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}*/
|
||||
|
||||
body {
|
||||
font-family: DejaVu Sans Mono;
|
||||
font-size: 10pt;
|
||||
}
|
||||
|
||||
td {
|
||||
width: 100%;
|
||||
display: inline;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
h1,h2,h3,h4 {
|
||||
margin-top: 1%;
|
||||
margin-bottom: 0.75%;
|
||||
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0.75%;
|
||||
margin-bottom: 0.75%;
|
||||
}
|
||||
|
||||
ul {
|
||||
margin-top: 0%;
|
||||
}
|
||||
|
||||
.current {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
pre {
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #3f51b5;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: #3f51b5;
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
<p><br>
|
||||
</p>
|
||||
<h1>alex_s168</h1>
|
||||
<p><br>
|
||||
</p>
|
||||
<p>Articles (<a href="atom.xml">Atom feed</a>) <br>
|
||||
</p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;"><a href="compiler-inlining.typ.desktop.html">Automatically inlining functions is not easy</a></span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;"><a href="compiler-pattern-matching.typ.desktop.html">Approaches to pattern matching in compilers</a></span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;"><a href="article-favicon.typ.desktop.html">The making of the favicon</a></span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">└─</span> <span class style="flex:1;"><a href="article-make-regex-engine-1.typ.desktop.html">Making a simple RegEx engine:
|
||||
Part 1: Introduction to RegEx</a></span></span></p>
|
||||
<p><br>
|
||||
</p>
|
||||
<p>Socials <br>
|
||||
</p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;"><a href="https://github.com/alex-s168">GitHub</a></span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;">Discord: alex_s168</span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;"><a href="mailto:alexandernutz68@gmail.com">E-Mail</a></span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;"><a href="https://njump.me/npub17semnd065ahhsajlylkyd3lahcykpuw45rhj7cge3uqdfq24y84st0g4gr">nostr</a></span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">└─</span> <span class style="flex:1;"><a href="https://codeberg.org/alex-s168">Codeberg</a></span></span></p>
|
||||
<p><br>
|
||||
</p>
|
||||
<p>Noteable projects <br>
|
||||
</p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;">Programming languages and compilers</span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">| ├─</span> <span class style="flex:1;"><a href="https://github.com/vxcc-backend/vxcc-new">vxcc</a>: WiP multi-level compiler</span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">| ├─</span> <span class style="flex:1;"><a href="https://github.com/alex-s168/uiuac">uiuac</a>: (discontinued) Optimizing compiler for the <a href="https://uiua.org">Uiua programming language</a></span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">| ├─</span> <span class style="flex:1;"><a href="https://github.com/Lambda-Mountain-Compiler-Backend/lambda-mountain">LSTS’s standard library</a></span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">| ├─</span> <span class style="flex:1;">FP programming language compiler mostly using <a href="https://en.wikipedia.org/wiki/Interaction_nets">interaction nets</a></span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">| └─</span> <span class style="flex:1;"><a href="https://github.com/alex-s168/lil-rs">lil-rs</a>: WiP implementation of <a href="http://beyondloom.com/decker/lil.html">lil</a></span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;">Misc.</span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">| ├─</span> <span class style="flex:1;"><a href="https://github.com/alex-s168/tpre">tpre</a>: Fast and minimal RegEx engine</span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">| └─</span> <span class style="flex:1;">nostr relay implementation</span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;">PCBs</span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">| └─</span> <span class style="flex:1;"><a href="project-etc-nand.typ.desktop.html">etc-nand</a>: <a href="https://github.com/ETC-A/etca-spec/">ETC.A</a> CPU from NAND gates</span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">└─</span> <span class style="flex:1;">FPGA designs</span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;"> ├─</span> <span class style="flex:1;">RMII MAC in <a href="https://www.chisel-lang.org/">Chisel</a></span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;"> └─</span> <span class style="flex:1;">Configurable AES accelerator in <a href="https://www.chisel-lang.org/">Chisel</a></span></span></p>
|
||||
<p><br>
|
||||
Skills <br>
|
||||
</p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;">Programming languages</span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">| ├─</span> <span class style="flex:1;">C++ and C</span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">| ├─</span> <span class style="flex:1;">Rust</span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">| ├─</span> <span class style="flex:1;"><a href="https://uiua.org">Uiua</a></span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">| └─</span> <span class style="flex:1;">Python, Lua, …</span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;">Writing compiler frontends but mostly backends</span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;">Hardware design with <a href="https://www.chisel-lang.org/">Chisel</a> and Verilog</span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">└─</span> <span class style="flex:1;">Internals of MLIR</span></span></p>
|
||||
<p><br>
|
||||
<br>
|
||||
This website is written almost entirely in <a href="https://typst.app/docs">typst</a>.</p>
|
||||
<p><a href="https://github.com/alex-s168/website">Website source code</a></p>
|
||||
<p><br>
|
||||
<br>
|
||||
Latest version of my badge:<br><span style="
|
||||
border:1pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:1.6pt;display:inline-block"><code style="white-space: pre-wrap">https://alex.vxcc.dev/res/badge.png</code></span></p>
|
||||
<p><br>
|
||||
Check out these websites:<br></p>
|
||||
<script>
|
||||
|
||||
function gotoVariant(variant) {
|
||||
window.location.href = window.location.href.replace(/\.\w+.html/g, variant);
|
||||
}
|
||||
|
||||
window.addEventListener('beforeprint', (event) => {
|
||||
gotoVariant('.min.pdf');
|
||||
});
|
||||
|
||||
</script>
|
||||
<script src="coffee.js" async>
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@@ -1 +0,0 @@
|
||||
build/index.typ.min.html: common.typ pages/index.typ core-page-style.typ build/pages.typ simple-page-layout.typ
|
Binary file not shown.
@@ -1 +0,0 @@
|
||||
build/index.typ.min.pdf: common.typ pages/index.typ core-page-style.typ build/pages.typ simple-page-layout.typ
|
@@ -1,68 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Alexander Nutz</title>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<p><br>
|
||||
</p>
|
||||
<h1>alex_s168</h1>
|
||||
<p><br>
|
||||
</p>
|
||||
<p>Articles (<a href="atom.xml">Atom feed</a>) <br>
|
||||
</p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;"><a href="compiler-inlining.typ.desktop.html">Automatically inlining functions is not easy</a></span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;"><a href="compiler-pattern-matching.typ.desktop.html">Approaches to pattern matching in compilers</a></span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;"><a href="article-favicon.typ.desktop.html">The making of the favicon</a></span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">└─</span> <span class style="flex:1;"><a href="article-make-regex-engine-1.typ.desktop.html">Making a simple RegEx engine:
|
||||
Part 1: Introduction to RegEx</a></span></span></p>
|
||||
<p><br>
|
||||
</p>
|
||||
<p>Socials <br>
|
||||
</p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;"><a href="https://github.com/alex-s168">GitHub</a></span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;">Discord: alex_s168</span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;"><a href="mailto:alexandernutz68@gmail.com">E-Mail</a></span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;"><a href="https://njump.me/npub17semnd065ahhsajlylkyd3lahcykpuw45rhj7cge3uqdfq24y84st0g4gr">nostr</a></span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">└─</span> <span class style="flex:1;"><a href="https://codeberg.org/alex-s168">Codeberg</a></span></span></p>
|
||||
<p><br>
|
||||
</p>
|
||||
<p>Noteable projects <br>
|
||||
</p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;">Programming languages and compilers</span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">| ├─</span> <span class style="flex:1;"><a href="https://github.com/vxcc-backend/vxcc-new">vxcc</a>: WiP multi-level compiler</span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">| ├─</span> <span class style="flex:1;"><a href="https://github.com/alex-s168/uiuac">uiuac</a>: (discontinued) Optimizing compiler for the <a href="https://uiua.org">Uiua programming language</a></span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">| ├─</span> <span class style="flex:1;"><a href="https://github.com/Lambda-Mountain-Compiler-Backend/lambda-mountain">LSTS’s standard library</a></span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">| ├─</span> <span class style="flex:1;">FP programming language compiler mostly using <a href="https://en.wikipedia.org/wiki/Interaction_nets">interaction nets</a></span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">| └─</span> <span class style="flex:1;"><a href="https://github.com/alex-s168/lil-rs">lil-rs</a>: WiP implementation of <a href="http://beyondloom.com/decker/lil.html">lil</a></span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;">Misc.</span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">| ├─</span> <span class style="flex:1;"><a href="https://github.com/alex-s168/tpre">tpre</a>: Fast and minimal RegEx engine</span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">| └─</span> <span class style="flex:1;">nostr relay implementation</span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;">PCBs</span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">| └─</span> <span class style="flex:1;"><a href="project-etc-nand.typ.desktop.html">etc-nand</a>: <a href="https://github.com/ETC-A/etca-spec/">ETC.A</a> CPU from NAND gates</span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">└─</span> <span class style="flex:1;">FPGA designs</span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;"> ├─</span> <span class style="flex:1;">RMII MAC in <a href="https://www.chisel-lang.org/">Chisel</a></span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;"> └─</span> <span class style="flex:1;">Configurable AES accelerator in <a href="https://www.chisel-lang.org/">Chisel</a></span></span></p>
|
||||
<p><br>
|
||||
Skills <br>
|
||||
</p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;">Programming languages</span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">| ├─</span> <span class style="flex:1;">C++ and C</span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">| ├─</span> <span class style="flex:1;">Rust</span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">| ├─</span> <span class style="flex:1;"><a href="https://uiua.org">Uiua</a></span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">| └─</span> <span class style="flex:1;">Python, Lua, …</span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;">Writing compiler frontends but mostly backends</span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;">Hardware design with <a href="https://www.chisel-lang.org/">Chisel</a> and Verilog</span></span></p>
|
||||
<p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">└─</span> <span class style="flex:1;">Internals of MLIR</span></span></p>
|
||||
<p><br>
|
||||
<br>
|
||||
This website is written almost entirely in <a href="https://typst.app/docs">typst</a>.</p>
|
||||
<p><a href="https://github.com/alex-s168/website">Website source code</a></p>
|
||||
<p><br>
|
||||
<br>
|
||||
Latest version of my badge:<br><code><code style="white-space: pre-wrap">https://alex.vxcc.dev/res/badge.png</code></code></p>
|
||||
<p><br>
|
||||
Check out these websites:<br></p>
|
||||
</body>
|
||||
</html>
|
@@ -1 +0,0 @@
|
||||
build/index.typ.nano.html: common.typ pages/index.typ core-page-style.typ build/pages.typ simple-page-layout.typ
|
@@ -1 +0,0 @@
|
||||
[{"url": "article-gpu-arch-1.typ.desktop.html", "page": "article-gpu-arch-1.typ", "in-feed": false, "in-homepage": false, "authors": [{"nick": "alex_s168", "name": "Alexander Nutz", "url": "https://alex.vxcc.dev", "badge": "https://alex.vxcc.dev/res/badge.png", "mail": "nutz.alexander@vxcc.dev"}], "title": "Designing a GPU architecture: Waves", "summary": "Exploring GPU architecture and designing our own. Part 1: wavefronts / warps", "modified": "2025-08-26T21:13:01+02:00"}, {"url": "compiler-inlining.typ.desktop.html", "page": "compiler-inlining.typ", "in-feed": true, "in-homepage": true, "authors": [{"nick": "alex_s168", "name": "Alexander Nutz", "url": "https://alex.vxcc.dev", "badge": "https://alex.vxcc.dev/res/badge.png", "mail": "nutz.alexander@vxcc.dev"}], "title": "Automatically inlining functions is not easy", "summary": "Compiler backends should automatically inline functions, to get rid to avoid function call overhead. A greedy approach has many issues. We'll be exploring a better approach.", "modified": "2025-08-11T16:38:10+02:00"}, {"url": "compiler-pattern-matching.typ.desktop.html", "page": "compiler-pattern-matching.typ", "in-feed": true, "in-homepage": true, "authors": [{"nick": "alex_s168", "name": "Alexander Nutz", "url": "https://alex.vxcc.dev", "badge": "https://alex.vxcc.dev/res/badge.png", "mail": "nutz.alexander@vxcc.dev"}], "title": "Approaches to pattern matching in compilers", "summary": "If you are working an more advanced compilers, you probably had to work with pattern matching already. In this article, we will explore different approaches.", "modified": "2025-08-19T09:55:17+02:00"}, {"url": "article-favicon.typ.desktop.html", "page": "article-favicon.typ", "in-feed": true, "in-homepage": true, "authors": [{"nick": "alex_s168", "name": "Alexander Nutz", "url": "https://alex.vxcc.dev", "badge": "https://alex.vxcc.dev/res/badge.png", "mail": "nutz.alexander@vxcc.dev"}], "title": "The making of the favicon", "summary": "It turns out that websites need a favicon, and making one is hard...", "modified": "2025-07-26T15:04:04+02:00"}, {"url": "article-make-regex-engine-1.typ.desktop.html", "page": "article-make-regex-engine-1.typ", "in-feed": true, "in-homepage": true, "authors": [{"nick": "alex_s168", "name": "Alexander Nutz", "url": "https://alex.vxcc.dev", "badge": "https://alex.vxcc.dev/res/badge.png", "mail": "nutz.alexander@vxcc.dev"}], "title": "Making a simple RegEx engine:\nPart 1: Introduction to RegEx", "summary": "Do you also think that all RegEx engines kinda suck and you want to make your own? probably not", "modified": "2025-07-26T14:20:22+02:00"}]
|
@@ -1,82 +0,0 @@
|
||||
#let articles = (
|
||||
(
|
||||
url: "article-gpu-arch-1.typ.desktop.html",
|
||||
page: "article-gpu-arch-1.typ",
|
||||
in-feed: false,
|
||||
in-homepage: false,
|
||||
authors: ((
|
||||
nick: "alex_s168",
|
||||
name: "Alexander Nutz",
|
||||
url: "https://alex.vxcc.dev",
|
||||
badge: "https://alex.vxcc.dev/res/badge.png",
|
||||
mail: "nutz.alexander@vxcc.dev"
|
||||
)),
|
||||
title: "Designing a GPU architecture: Waves",
|
||||
summary: "Exploring GPU architecture and designing our own. Part 1: wavefronts / warps",
|
||||
modified: "2025-08-26T21:13:01+02:00"
|
||||
),
|
||||
(
|
||||
url: "compiler-inlining.typ.desktop.html",
|
||||
page: "compiler-inlining.typ",
|
||||
in-feed: true,
|
||||
in-homepage: true,
|
||||
authors: ((
|
||||
nick: "alex_s168",
|
||||
name: "Alexander Nutz",
|
||||
url: "https://alex.vxcc.dev",
|
||||
badge: "https://alex.vxcc.dev/res/badge.png",
|
||||
mail: "nutz.alexander@vxcc.dev"
|
||||
)),
|
||||
title: "Automatically inlining functions is not easy",
|
||||
summary: "Compiler backends should automatically inline functions, to get rid to avoid function call overhead. A greedy approach has many issues. We'll be exploring a better approach.",
|
||||
modified: "2025-08-11T16:38:10+02:00"
|
||||
),
|
||||
(
|
||||
url: "compiler-pattern-matching.typ.desktop.html",
|
||||
page: "compiler-pattern-matching.typ",
|
||||
in-feed: true,
|
||||
in-homepage: true,
|
||||
authors: ((
|
||||
nick: "alex_s168",
|
||||
name: "Alexander Nutz",
|
||||
url: "https://alex.vxcc.dev",
|
||||
badge: "https://alex.vxcc.dev/res/badge.png",
|
||||
mail: "nutz.alexander@vxcc.dev"
|
||||
)),
|
||||
title: "Approaches to pattern matching in compilers",
|
||||
summary: "If you are working an more advanced compilers, you probably had to work with pattern matching already. In this article, we will explore different approaches.",
|
||||
modified: "2025-08-19T09:55:17+02:00"
|
||||
),
|
||||
(
|
||||
url: "article-favicon.typ.desktop.html",
|
||||
page: "article-favicon.typ",
|
||||
in-feed: true,
|
||||
in-homepage: true,
|
||||
authors: ((
|
||||
nick: "alex_s168",
|
||||
name: "Alexander Nutz",
|
||||
url: "https://alex.vxcc.dev",
|
||||
badge: "https://alex.vxcc.dev/res/badge.png",
|
||||
mail: "nutz.alexander@vxcc.dev"
|
||||
)),
|
||||
title: "The making of the favicon",
|
||||
summary: "It turns out that websites need a favicon, and making one is hard...",
|
||||
modified: "2025-07-26T15:04:04+02:00"
|
||||
),
|
||||
(
|
||||
url: "article-make-regex-engine-1.typ.desktop.html",
|
||||
page: "article-make-regex-engine-1.typ",
|
||||
in-feed: true,
|
||||
in-homepage: true,
|
||||
authors: ((
|
||||
nick: "alex_s168",
|
||||
name: "Alexander Nutz",
|
||||
url: "https://alex.vxcc.dev",
|
||||
badge: "https://alex.vxcc.dev/res/badge.png",
|
||||
mail: "nutz.alexander@vxcc.dev"
|
||||
)),
|
||||
title: "Making a simple RegEx engine:\nPart 1: Introduction to RegEx",
|
||||
summary: "Do you also think that all RegEx engines kinda suck and you want to make your own? probably not",
|
||||
modified: "2025-07-26T14:20:22+02:00"
|
||||
)
|
||||
)
|
@@ -1,257 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>etc-nand</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="icon" sizes="512x512" href="res/favicon.png">
|
||||
<link rel="image_src" type="image/png" href="res/favicon.png">
|
||||
<link type="application/atom+xml" rel="alternate" title="alexs168's blog" href="atom.xml">
|
||||
</head>
|
||||
<body>
|
||||
<style>
|
||||
|
||||
@font-face {
|
||||
font-family: 'DejaVu Sans Mono';
|
||||
src:local('DejaVu Sans Mono'),
|
||||
url('res/DejaVuSansMono.woff2') format('woff2'),
|
||||
local('Courier New'),
|
||||
local(Courier),
|
||||
local(monospace);
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
/*
|
||||
@font-face {
|
||||
font-family: 'DejaVu Sans Mono';
|
||||
src:local('DejaVu Sans Mono'),
|
||||
url('res/DejaVuSansMono-Bold.woff2') format('woff2'),
|
||||
local('Courier New'),
|
||||
local(Courier),
|
||||
local(monospace);
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'DejaVu Sans';
|
||||
src:local('DejaVu Sans'),
|
||||
url('res/DejaVuSans-Bold.woff2') format('woff2'),
|
||||
local('Courier New');
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'DejaVu Sans';
|
||||
src:local('DejaVu Sans'),
|
||||
url('res/DejaVuSans.woff2') format('woff2'),
|
||||
local('Courier New');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}*/
|
||||
|
||||
body {
|
||||
font-family: DejaVu Sans Mono;
|
||||
font-size: 17pt;
|
||||
}
|
||||
|
||||
td {
|
||||
width: 100%;
|
||||
display: inline;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
h1,h2,h3,h4 {
|
||||
margin-top: 1%;
|
||||
margin-bottom: 0.75%;
|
||||
margin-left: -0.75%;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0.75%;
|
||||
margin-bottom: 0.75%;
|
||||
}
|
||||
|
||||
ul {
|
||||
margin-top: 0%;
|
||||
}
|
||||
|
||||
.current {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
pre {
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #3f51b5;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: #3f51b5;
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
<table>
|
||||
<tr>
|
||||
<td><span class="sidebar" style><span class="column-fixed" style="display: inline-flex; position: fixed; justify-content: center; width: 25%"><table><tr><td><span class="table-of-contents" style><div style="
|
||||
border:1.2pt solid black;
|
||||
border-radius:2pt;
|
||||
|
||||
|
||||
padding:3%;"><p><span style="text-decoration: underline">Table of contents</span><br></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;"><span class="headingr" id="headingr-0"><a href="#loc-1">Overview</a></span></span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">| ├─</span> <span class style="flex:1;"><span class="headingr" id="headingr-1"><a href="#loc-2">Estimates</a></span></span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">| └─</span> <span class style="flex:1;"><span class="headingr" id="headingr-2"><a href="#loc-3">Planned Specifications</a></span></span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">├─</span> <span class style="flex:1;"><span class="headingr" id="headingr-3"><a href="#loc-4">Purchase</a></span></span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;">└─</span> <span class style="flex:1;"><span class="headingr" id="headingr-4"><a href="#loc-5">Images</a></span></span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;"> ├─</span> <span class style="flex:1;"><span class="headingr" id="headingr-5"><a href="#loc-6">16 bit register</a></span></span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;"> ├─</span> <span class style="flex:1;"><span class="headingr" id="headingr-6"><a href="#loc-7">8 bit ALU slice</a></span></span></span></p><p style="line-height:1.1"><span class style="display:flex; text-indent:0pt;"><span class style="margin-right: 11pt;"> └─</span> <span class style="flex:1;"><span class="headingr" id="headingr-7"><a href="#add8">8 bit adder</a></span></span></span></p></div></span><span class="table-of-contents" style><script>document.addEventListener('DOMContentLoaded', function() {
|
||||
let tags = ['h2', 'h3', 'h4'].flatMap(x => Array.from(document.getElementsByTagName(x))).sort((a, b) => a.getBoundingClientRect().top - b.getBoundingClientRect().top);
|
||||
let pageHeight = document.documentElement.scrollHeight-window.innerHeight;
|
||||
document.addEventListener('scroll', (event) => {
|
||||
let progress = -(document.documentElement.getBoundingClientRect().y / pageHeight);
|
||||
let delta = progress * window.innerHeight;
|
||||
let idx = tags.map(x => 0 > x.getBoundingClientRect().top - delta).lastIndexOf(true);
|
||||
Array.from(document.getElementsByClassName('headingr')).map(x => x.classList.remove('current'));
|
||||
if (idx != -1) {
|
||||
document.getElementById('headingr-' + idx).classList.add('current');
|
||||
}
|
||||
}
|
||||
);
|
||||
})</script><style>
|
||||
.table-of-contents > p > span { width: 100%; }
|
||||
</style></span></td></tr><tr><td><br>
|
||||
<a href="index.html"><b>Website Home</b></a> <br>
|
||||
</td></tr><tr><td><p>Renderings of this page:</p><ul><li><a href="#" onclick="gotoVariant(".min.pdf");">minimal PDF (printable)</a></li><li><a href="#" onclick="gotoVariant(".nano.html");">minimal HTML</a></li></ul></td></tr><tr><td><a href="atom.xml">Atom feed</a> <br>
|
||||
</td></tr><tr><td><style>
|
||||
@media only screen and (max-width: 1200px) {
|
||||
.sidebar {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.column-fixed {
|
||||
width: 0% !important;
|
||||
}
|
||||
|
||||
.body-column {
|
||||
left: 3% !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1800px) {
|
||||
.body-column > span {
|
||||
width: 75% !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1200px) {
|
||||
.body-column {
|
||||
width: 97% !important;
|
||||
}
|
||||
.body-column > span {
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
|
||||
.hide { display: inline; background: black; transition: background 0.3s linear; }
|
||||
.hide:hover, .hide:focus { background: transparent; }
|
||||
</style></td></tr></table><style>
|
||||
.column-fixed > table > tbody > tr > td > * { width: 100%; }
|
||||
</style></span></span></td>
|
||||
<td><span class="body-column" style="position: absolute; left: 28%; width: 72%"><span style="
|
||||
|
||||
|
||||
width:50%;
|
||||
|
||||
display:inline-block"><div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><p><br></p><h1>etc-nand</h1></div><div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><br>You can click the PCB images to switch to the other side.</div><div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><p><br><span id="loc-1" style="text-decoration: underline"><h2>Overview</h2></span></p><p>etc-nand is a real-world <a href="https://github.com/ETC-A/etca-spec/">ETC.A</a> CPU built from almost only quad NAND gate ICs (74hc00)</p><p>It will probably be finished in a few months.</p></div><div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><p><br><span id="loc-2" style="text-decoration: underline"><h3>Estimates</h3></span></p><p>Estimated gate count:</p><ul><li>2800 NAND gates</li><li>320 tristate buffers</li></ul><p><br>
|
||||
Estimated component counts:</p><ul><li>700x 74hc00 quad NAND gates</li><li>40x 74HC54 octal tristate buffers</li><li>a few simple resistors</li></ul></div><div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><p><br><span id="loc-3" style="text-decoration: underline"><h3>Planned Specifications</h3></span> ETC.A base instruction set + byte operations + S&F + Von Neumann</p><p>The CPU will communicate with peripherals over a 16 bit data + 15 bit address memory bus</p></div><div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><p><br><span id="loc-4" style="text-decoration: underline"><h2>Purchase</h2></span> You will be able to purchase one in the future.</p><p>Stay tuned!</p></div><div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><br><span id="loc-5" style="text-decoration: underline"><h2>Images</h2></span> Images of PCBs that are either already manifactured or currently beeing manifactured by JLCPCB.</div><div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><p><br><span id="loc-6" style="text-decoration: underline"><h3>16 bit register</h3></span></p><img draggable="false" tite="Click Me!" src="res/etc-nand/reg16_front.png" data-other="res/etc-nand/reg16_back.png" onclick="swapFrontBack(this);" style="width:80%; cursor:pointer;"><script>
|
||||
function swapFrontBack(img) {
|
||||
let oldsrc = img.src;
|
||||
img.src = img.dataset.other;
|
||||
img.dataset.other = oldsrc;
|
||||
}
|
||||
</script></div><div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><p><br><span id="loc-7" style="text-decoration: underline"><h3>8 bit ALU slice</h3></span> A <a href="#add8">8 bit adder module</a> will be placed in the middle</p><img draggable="false" tite="Click Me!" src="res/etc-nand/alu8_front.png" data-other="res/etc-nand/alu8_back.png" onclick="swapFrontBack(this);" style="width:80%; cursor:pointer;"><script>
|
||||
function swapFrontBack(img) {
|
||||
let oldsrc = img.src;
|
||||
img.src = img.dataset.other;
|
||||
img.dataset.other = oldsrc;
|
||||
}
|
||||
</script></div><div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><p><br><span id="add8" style="text-decoration: underline"><h3>8 bit adder</h3></span></p><img draggable="false" tite="Click Me!" src="res/etc-nand/add8_front.png" data-other="res/etc-nand/add8_back.png" onclick="swapFrontBack(this);" style="width:80%; cursor:pointer;"><script>
|
||||
function swapFrontBack(img) {
|
||||
let oldsrc = img.src;
|
||||
img.src = img.dataset.other;
|
||||
img.dataset.other = oldsrc;
|
||||
}
|
||||
</script></div></span></span></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
<script>
|
||||
|
||||
function gotoVariant(variant) {
|
||||
window.location.href = window.location.href.replace(/\.\w+.html/g, variant);
|
||||
}
|
||||
|
||||
window.addEventListener('beforeprint', (event) => {
|
||||
gotoVariant('.min.pdf');
|
||||
});
|
||||
|
||||
</script>
|
||||
<script src="coffee.js" async>
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@@ -1 +0,0 @@
|
||||
build/project-etc-nand.typ.desktop.html: components/header.typ common.typ pages/project-etc-nand.typ core-page-style.typ components/pcb-view.typ simple-page-layout.typ
|
@@ -1 +0,0 @@
|
||||
--input git_rev=edc0a2d5baf5ed25932523f6ce5ac47b46df211c --input git_commit_date="23. July 2025 09:31"
|
@@ -1 +0,0 @@
|
||||
2025-07-23T09:31:06+02:00
|
@@ -1,209 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>etc-nand</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="icon" sizes="512x512" href="res/favicon.png">
|
||||
<link rel="image_src" type="image/png" href="res/favicon.png">
|
||||
<link type="application/atom+xml" rel="alternate" title="alexs168's blog" href="atom.xml">
|
||||
</head>
|
||||
<body>
|
||||
<style>
|
||||
|
||||
@font-face {
|
||||
font-family: 'DejaVu Sans Mono';
|
||||
src:local('DejaVu Sans Mono'),
|
||||
url('res/DejaVuSansMono.woff2') format('woff2'),
|
||||
local('Courier New'),
|
||||
local(Courier),
|
||||
local(monospace);
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
/*
|
||||
@font-face {
|
||||
font-family: 'DejaVu Sans Mono';
|
||||
src:local('DejaVu Sans Mono'),
|
||||
url('res/DejaVuSansMono-Bold.woff2') format('woff2'),
|
||||
local('Courier New'),
|
||||
local(Courier),
|
||||
local(monospace);
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'DejaVu Sans';
|
||||
src:local('DejaVu Sans'),
|
||||
url('res/DejaVuSans-Bold.woff2') format('woff2'),
|
||||
local('Courier New');
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'DejaVu Sans';
|
||||
src:local('DejaVu Sans'),
|
||||
url('res/DejaVuSans.woff2') format('woff2'),
|
||||
local('Courier New');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}*/
|
||||
|
||||
body {
|
||||
font-family: DejaVu Sans Mono;
|
||||
font-size: 10pt;
|
||||
}
|
||||
|
||||
td {
|
||||
width: 100%;
|
||||
display: inline;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
h1,h2,h3,h4 {
|
||||
margin-top: 1%;
|
||||
margin-bottom: 0.75%;
|
||||
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0.75%;
|
||||
margin-bottom: 0.75%;
|
||||
}
|
||||
|
||||
ul {
|
||||
margin-top: 0%;
|
||||
}
|
||||
|
||||
.current {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
pre {
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #3f51b5;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: #3f51b5;
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h1>etc-nand</h1>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br><span style="text-decoration: underline"><h2>Overview</h2></span></p>
|
||||
<p>etc-nand is a real-world <a href="https://github.com/ETC-A/etca-spec/">ETC.A</a> CPU built from almost only quad NAND gate ICs (74hc00)</p>
|
||||
<p>It will probably be finished in a few months.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br><span style="text-decoration: underline"><h3>Estimates</h3></span></p>
|
||||
<p>Estimated gate count:</p>
|
||||
<ul>
|
||||
<li>2800 NAND gates</li>
|
||||
<li>320 tristate buffers</li>
|
||||
</ul>
|
||||
<p><br>
|
||||
Estimated component counts:</p>
|
||||
<ul>
|
||||
<li>700x 74hc00 quad NAND gates</li>
|
||||
<li>40x 74HC54 octal tristate buffers</li>
|
||||
<li>a few simple resistors</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br><span style="text-decoration: underline"><h3>Planned Specifications</h3></span> ETC.A base instruction set + byte operations + S&F + Von Neumann</p>
|
||||
<p>The CPU will communicate with peripherals over a 16 bit data + 15 bit address memory bus</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br><span style="text-decoration: underline"><h2>Purchase</h2></span> You will be able to purchase one in the future.</p>
|
||||
<p>Stay tuned!</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
"><br><span style="text-decoration: underline"><h2>Images</h2></span> Images of PCBs that are either already manifactured or currently beeing manifactured by JLCPCB.</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br><span style="text-decoration: underline"><h3>16 bit register</h3></span></p>
|
||||
<img src="res/etc-nand/reg16_front.png" style="width:100%;">
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br><span style="text-decoration: underline"><h3>8 bit ALU slice</h3></span> A <a href="#add8">8 bit adder module</a> will be placed in the middle</p>
|
||||
<img src="res/etc-nand/alu8_front.png" style="width:100%;">
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br><span id="add8" style="text-decoration: underline"><h3>8 bit adder</h3></span></p>
|
||||
<img src="res/etc-nand/add8_front.png" style="width:100%;">
|
||||
</div>
|
||||
<script>
|
||||
|
||||
function gotoVariant(variant) {
|
||||
window.location.href = window.location.href.replace(/\.\w+.html/g, variant);
|
||||
}
|
||||
|
||||
window.addEventListener('beforeprint', (event) => {
|
||||
gotoVariant('.min.pdf');
|
||||
});
|
||||
|
||||
</script>
|
||||
<script src="coffee.js" async>
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@@ -1 +0,0 @@
|
||||
build/project-etc-nand.typ.min.html: components/header.typ common.typ pages/project-etc-nand.typ core-page-style.typ components/pcb-view.typ simple-page-layout.typ
|
Binary file not shown.
@@ -1 +0,0 @@
|
||||
build/project-etc-nand.typ.min.pdf: res/etc-nand/alu8_back.png components/header.typ common.typ res/etc-nand/alu8_front.png components/pcb-view.typ res/etc-nand/add8_back.png res/etc-nand/reg16_back.png core-page-style.typ pages/project-etc-nand.typ res/etc-nand/add8_front.png res/etc-nand/reg16_front.png simple-page-layout.typ
|
@@ -1,113 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>etc-nand</title>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h1>etc-nand</h1>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h2>Overview</h2>
|
||||
<p>etc-nand is a real-world <a href="https://github.com/ETC-A/etca-spec/">ETC.A</a> CPU built from almost only quad NAND gate ICs (74hc00)</p>
|
||||
<p>It will probably be finished in a few months.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h3>Estimates</h3>
|
||||
<p>Estimated gate count:</p>
|
||||
<ul>
|
||||
<li>2800 NAND gates</li>
|
||||
<li>320 tristate buffers</li>
|
||||
</ul>
|
||||
<p><br>
|
||||
Estimated component counts:</p>
|
||||
<ul>
|
||||
<li>700x 74hc00 quad NAND gates</li>
|
||||
<li>40x 74HC54 octal tristate buffers</li>
|
||||
<li>a few simple resistors</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h3>Planned Specifications</h3>
|
||||
<p>ETC.A base instruction set + byte operations + S&F + Von Neumann</p>
|
||||
<p>The CPU will communicate with peripherals over a 16 bit data + 15 bit address memory bus</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h2>Purchase</h2>
|
||||
<p>You will be able to purchase one in the future.</p>
|
||||
<p>Stay tuned!</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h2>Images</h2>
|
||||
<p>Images of PCBs that are either already manifactured or currently beeing manifactured by JLCPCB.</p>
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h3>16 bit register</h3>
|
||||
<img src="res/etc-nand/reg16_front.png" style="width:100%;">
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h3>8 bit ALU slice</h3>
|
||||
<p>A <a href="#add8">8 bit adder module</a> will be placed in the middle</p>
|
||||
<img src="res/etc-nand/alu8_front.png" style="width:100%;">
|
||||
</div>
|
||||
<div style="
|
||||
|
||||
|
||||
|
||||
|
||||
">
|
||||
<p><br></p>
|
||||
<h3 id="add8">8 bit adder</h3>
|
||||
<img src="res/etc-nand/add8_front.png" style="width:100%;">
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@@ -1 +0,0 @@
|
||||
build/project-etc-nand.typ.nano.html: components/header.typ common.typ pages/project-etc-nand.typ core-page-style.typ components/pcb-view.typ simple-page-layout.typ
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user