@@ -7,7 +7,7 @@ MergeFunctions pass, how it works
7
7
8
8
Introduction
9
9
============
10
- Sometimes code contains equal functions, or functions that does exactly the same
10
+ Sometimes code contains equal functions, or functions that do exactly the same
11
11
thing even though they are non-equal on the IR level (e.g.: multiplication on 2
12
12
and 'shl 1'). It could happen due to several reasons: mainly, the usage of
13
13
templates and automatic code generators. Though, sometimes the user itself could
@@ -16,7 +16,7 @@ write the same thing twice :-)
16
16
The main purpose of this pass is to recognize such functions and merge them.
17
17
18
18
This document is the extension to pass comments and describes the pass logic. It
19
- describes the algorithm that is used in order to compare functions and
19
+ describes the algorithm used to compare functions and
20
20
explains how we could combine equal functions correctly to keep the module
21
21
valid.
22
22
@@ -58,7 +58,7 @@ It's especially important to understand chapter 3 of tutorial:
58
58
59
59
:doc: `tutorial/LangImpl03 `
60
60
61
- The reader should also know how passes work in LLVM. They could use this
61
+ The reader should also know how passes work in LLVM. They can use this
62
62
article as a reference and start point here:
63
63
64
64
:doc: `WritingAnLLVMPass `
@@ -68,7 +68,7 @@ debugging and bug-fixing.
68
68
69
69
Narrative structure
70
70
-------------------
71
- The article consists of three parts. The first part explains pass functionality
71
+ This article consists of three parts. The first part explains pass functionality
72
72
on the top-level. The second part describes the comparison procedure itself.
73
73
The third part describes the merging process.
74
74
@@ -130,7 +130,7 @@ access lookup? The answer is: "yes".
130
130
131
131
Random-access
132
132
"""""""""""""
133
- How it could this be done? Just convert each function to a number, and gather
133
+ How can this be done? Just convert each function to a number, and gather
134
134
all of them in a special hash-table. Functions with equal hashes are equal.
135
135
Good hashing means, that every function part must be taken into account. That
136
136
means we have to convert every function part into some number, and then add it
@@ -190,17 +190,17 @@ The algorithm is pretty simple:
190
190
191
191
1. Put all module's functions into the *worklist *.
192
192
193
- 2. Scan *worklist *'s functions twice: first enumerate only strong functions and
193
+ 2. Scan *worklist *'s functions twice: first, enumerate only strong functions and
194
194
then only weak ones:
195
195
196
196
2.1. Loop body: take a function from *worklist * (call it *FCur *) and try to
197
197
insert it into *FnTree *: check whether *FCur * is equal to one of functions
198
198
in *FnTree *. If there *is * an equal function in *FnTree *
199
- (call it *FExists *): merge function *FCur * with *FExists *. Otherwise add
199
+ (call it *FExists *): merge function *FCur * with *FExists *. Otherwise, add
200
200
the function from the *worklist * to *FnTree *.
201
201
202
202
3. Once the *worklist * scanning and merging operations are complete, check the
203
- *Deferred * list. If it is not empty: refill the *worklist * contents with
203
+ *Deferred * list. If it is not empty, refill the *worklist * contents with
204
204
*Deferred * list and redo step 2, if the *Deferred * list is empty, then exit
205
205
from method.
206
206
@@ -249,14 +249,14 @@ Below, we will use the following operations:
249
249
250
250
The rest of the article is based on *MergeFunctions.cpp * source code
251
251
(found in *<llvm_dir>/lib/Transforms/IPO/MergeFunctions.cpp *). We would like
252
- to ask reader to keep this file open, so we could use it as a reference
252
+ to ask the reader to keep this file open, so we could use it as a reference
253
253
for further explanations.
254
254
255
255
Now, we're ready to proceed to the next chapter and see how it works.
256
256
257
257
Functions comparison
258
258
====================
259
- At first , let's define how exactly we compare complex objects.
259
+ First , let's define exactly how we compare complex objects.
260
260
261
261
Complex object comparison (function, basic-block, etc) is mostly based on its
262
262
sub-object comparison results. It is similar to the next "tree" objects
@@ -307,7 +307,7 @@ to those we met later in function body (value we met first would be *less*).
307
307
This is done by “``FunctionComparator::cmpValues(const Value*, const Value*) ``”
308
308
method (will be described a bit later).
309
309
310
- 4. Function body comparison. As it written in method comments:
310
+ 4. Function body comparison. As written in method comments:
311
311
312
312
“We do a CFG-ordered walk since the actual ordering of the blocks in the linked
313
313
list is immaterial. Our walk starts at the entry block for both functions, then
@@ -477,7 +477,7 @@ Of course, we can combine insertion and comparison:
477
477
= sn_mapR.insert(std::make_pair(Right, sn_mapR.size()));
478
478
return cmpNumbers(LeftRes.first->second, RightRes.first->second);
479
479
480
- Let's look, how whole method could be implemented.
480
+ Let's look at how the whole method could be implemented.
481
481
482
482
1. We have to start with the bad news. Consider function self and
483
483
cross-referencing cases:
@@ -519,7 +519,7 @@ the result of numbers comparison:
519
519
if (LeftRes.first->second < RightRes.first->second) return -1;
520
520
return 1;
521
521
522
- Now when *cmpValues * returns 0, we can proceed the comparison procedure.
522
+ Now, when *cmpValues * returns 0, we can proceed with the comparison procedure.
523
523
Otherwise, if we get (-1 or 1), we need to pass this result to the top level,
524
524
and finish comparison procedure.
525
525
@@ -549,7 +549,7 @@ losslessly bitcasted to each other. The further explanation is modification of
549
549
2.1.3.1. If types are vectors, compare their bitwidth using the
550
550
*cmpNumbers *. If result is not 0, return it.
551
551
552
- 2.1.3.2. Different types, but not a vectors:
552
+ 2.1.3.2. Different types, but not vectors:
553
553
554
554
* if both of them are pointers, good for us, we can proceed to step 3.
555
555
* if one of types is pointer, return result of *isPointer * flags
@@ -654,7 +654,7 @@ O(N*N) to O(log(N)).
654
654
655
655
Merging process, mergeTwoFunctions
656
656
==================================
657
- Once *MergeFunctions * detected that current function (*G *) is equal to one that
657
+ Once *MergeFunctions * detects that current function (*G *) is equal to one that
658
658
were analyzed before (function *F *) it calls ``mergeTwoFunctions(Function*,
659
659
Function*) ``.
660
660
@@ -664,7 +664,7 @@ Operation affects ``FnTree`` contents with next way: *F* will stay in
664
664
functions that calls *G * would be put into ``Deferred `` set and removed from
665
665
``FnTree ``, and analyzed again.
666
666
667
- The approach is next :
667
+ The approach is as follows :
668
668
669
669
1. Most wished case: when we can use alias and both of *F * and *G * are weak. We
670
670
make both of them with aliases to the third strong function *H *. Actually *H *
@@ -691,12 +691,12 @@ ok: we can use alias to *F* instead of *G* or change call instructions itself.
691
691
692
692
HasGlobalAliases, removeUsers
693
693
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
694
- First consider the case when we have global aliases of one function name to
694
+ First, consider the case when we have global aliases of one function name to
695
695
another. Our purpose is make both of them with aliases to the third strong
696
696
function. Though if we keep *F * alive and without major changes we can leave it
697
697
in ``FnTree ``. Try to combine these two goals.
698
698
699
- Do stub replacement of *F * itself with an alias to *F *.
699
+ Do a stub replacement of *F * itself with an alias to *F *.
700
700
701
701
1. Create stub function *H *, with the same name and attributes like function
702
702
*F *. It takes maximum alignment of *F * and *G *.
@@ -725,7 +725,7 @@ also have alias to *F*.
725
725
726
726
No global aliases, replaceDirectCallers
727
727
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
728
- If global aliases are not supported. We call ``replaceDirectCallers ``. Just
728
+ If global aliases are not supported, we call ``replaceDirectCallers ``. Just
729
729
go through all calls of *G * and replace it with calls of *F *. If you look into
730
730
the method you will see that it scans all uses of *G * too, and if use is callee
731
731
(if user is call instruction and *G * is used as what to be called), we replace
0 commit comments