Skip to content

Commit 31ad50c

Browse files
committed
docs: Seperate documents
1 parent ef3d4e8 commit 31ad50c

File tree

3 files changed

+289
-280
lines changed

3 files changed

+289
-280
lines changed

DependencyChecker.md

Lines changed: 284 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,284 @@
1+
# Custom-LLVM for Interprocedural Dependencies Checking on Hardware Register.
2+
3+
한국어 : https://github.com/rollrat/custom-llvm2/blob/master/README.md
4+
5+
This custom-llvm has been forked to determine the variable dependencies (Dominated, Maybe)
6+
of the specific register specified by llvm.annotation in the IR step. This project can help
7+
you to output variable dependencies of the IR level from an object file(Not yet). See Commits
8+
for more details on the code changes. Also refer to the develop and test branches for testing
9+
and etcs.
10+
11+
***
12+
13+
## 1. Representation in the IR stage
14+
Please read the following article while referring to b.cpp and b.ll. [Test Folder](https://github.com/rollrat/custom-llvm2/tree/master/test/Dependency%20Test)
15+
16+
### 1.1. Variable marking using llvm.annotation
17+
`__attribute__((annotate("message")))` is an annotation feature provided by clang / llvm. This function allows you to know the annotated variables until the final stage of IR. You can also see the contents of `" message "` in an annotated variable.
18+
``` c++
19+
int __attribute__((annotate("a"))) a = 0;
20+
```
21+
``` llvm
22+
@.str.2 = private unnamed_addr constant [2 x i8] c"a\00", section "llvm.metadata"
23+
24+
%a = alloca i32, align 4
25+
%1 = bitcast i32* %a to i8*
26+
call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %1) #2
27+
call void @llvm.var.annotation(i8* nonnull %1, i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.2, i32 0, i32 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str.1, i32 0, i32 0), i32 10)
28+
```
29+
The variable `a` has been annotated via the above C ++ syntax. The following IR representation shows that the function `@ llvm.var.annotation` calls `%1` and that `%1` bitcasts`%a`. `%a` points to the annotated variable a. With the llvm annotation function, `StoreInst` tells which values are assigned to`%a`.
30+
``` llvm
31+
%add4 = add nsw i32 %4, %call
32+
store i32 %add4, i32* %a, align 4, !tbaa !3
33+
```
34+
The above statement shows that the value of `%add4` is stored in `%a`. This function works on all annotated variables and does not disappear in the optimization phase.
35+
36+
### 1.2. Variable marking via extern function
37+
When variable marking using `llvm.annotation`, I found that marking disappears in some situations during maximum optimization on testing.
38+
We could not find another way to mark the variable itself, but we could find the virtual register used in the process of changing the variable by calling the bodyless function.
39+
``` c++
40+
#define ANNORATE(msg) __attribute__((annotate(msg)))
41+
extern void __my__annotate(void *);
42+
43+
void SHA256_Mixing(SHA_PULONG indexs, SHA_PULONG outdexs)
44+
{
45+
SHA_ULONG w[64];
46+
SHA_ULONG i, a, b, c, d, e, f, g, h, ANNORATE("t1") t1, ANNORATE("t2") t2;
47+
48+
for (i = 0; i < 16; i++)
49+
w[i] = CONVERT_TO_LITTLE_ENDIAN(indexs[i]);
50+
51+
for (i = 16; i < 64; i++)
52+
w[i] = SHA_256_s0(w[i - 15]) + w[i - 16] + w[i - 7] + SHA_256_s1(w[i - 2]);
53+
54+
for (i = 0; i < 64; i++) {
55+
56+
__my__annotate(t1);
57+
SHA_256_LOOP(a, b, c, d, e, f, g, h, i, t1, t2);
58+
SHA_256_XROLL(a, b, c, d, e, f, g, h, t1, t2);
59+
}
60+
```
61+
The above t1 is marked, but no annotation is left in -O2 optimization. With the extern function, you can get the following results from the .ll file:
62+
``` llvm
63+
; Before
64+
for.body73: ; preds = %for.body73, %for.end62
65+
%add112215 = phi i32 [ %26, %for.end62 ], [ %add112, %for.body73 ]
66+
%i.2214 = phi i32 [ 0, %for.end62 ], [ %inc114, %for.body73 ]
67+
%h.0213 = phi i32 [ %35, %for.end62 ], [ %g.0212, %for.body73 ]
68+
%g.0212 = phi i32 [ %34, %for.end62 ], [ %f.0211, %for.body73 ]
69+
%f.0211 = phi i32 [ %33, %for.end62 ], [ %e.0210, %for.body73 ]
70+
%e.0210 = phi i32 [ %32, %for.end62 ], [ %add111, %for.body73 ]
71+
%d.0209 = phi i32 [ %31, %for.end62 ], [ %c.0208, %for.body73 ]
72+
%c.0208 = phi i32 [ %30, %for.end62 ], [ %b.0207, %for.body73 ]
73+
%b.0207 = phi i32 [ %29, %for.end62 ], [ %add112215, %for.body73 ]
74+
%shr74 = lshr i32 %e.0210, 6
75+
%shl75 = shl i32 %e.0210, 26
76+
%or76 = or i32 %shr74, %shl75
77+
%shr77 = lshr i32 %e.0210, 11
78+
%shl78 = shl i32 %e.0210, 21
79+
...
80+
81+
; After
82+
for.body73: ; preds = %for.body73, %for.end62
83+
%t1.0216 = phi i32 [ undef, %for.end62 ], [ %add93, %for.body73 ]
84+
%h.0215 = phi i32 [ %31, %for.end62 ], [ %g.0214, %for.body73 ]
85+
%g.0214 = phi i32 [ %30, %for.end62 ], [ %f.0213, %for.body73 ]
86+
%f.0213 = phi i32 [ %29, %for.end62 ], [ %e.0212, %for.body73 ]
87+
%e.0212 = phi i32 [ %28, %for.end62 ], [ %add111, %for.body73 ]
88+
%d.0211 = phi i32 [ %27, %for.end62 ], [ %c.0210, %for.body73 ]
89+
%c.0210 = phi i32 [ %26, %for.end62 ], [ %b.0209, %for.body73 ]
90+
%b.0209 = phi i32 [ %25, %for.end62 ], [ %35, %for.body73 ]
91+
%i.2208 = phi i32 [ 0, %for.end62 ], [ %inc114, %for.body73 ]
92+
%32 = inttoptr i32 %t1.0216 to i8*
93+
; extern function called
94+
call void @__my__annotate(i8* %32) #2
95+
%shr74 = lshr i32 %e.0212, 6
96+
%shl75 = shl i32 %e.0212, 26
97+
%or76 = or i32 %shr74, %shl75
98+
%shr77 = lshr i32 %e.0212, 11
99+
%shl78 = shl i32 %e.0212, 21
100+
```
101+
Like this, when marking with extern function, the kind of marking of argument of function is marked as `Annotated` which will be described below.
102+
The extern function used is removed from llc processing via `eraseFromParent`.
103+
104+
***
105+
106+
107+
## 2. Dependency Pass
108+
This is the pass to mark the dependency of the variable in the Instruction. It is executed once for each function just before the SDNode generation, not the optimization step.
109+
This [link](https://github.com/rollrat/custom-llvm2/commit/583681378edf38a3d837135f9815c621c3021590#diff-825e43e63961002d7541aec6d4d4f7a4R468)
110+
Indicates the above procedure. You can know that `c-> runOnFunction` immediately precedes the creation of the SDNode by` SelectAllBasicBlocks`.
111+
112+
The source of the following links is a full source code of Dependency Pass.
113+
```
114+
https://github.com/rollrat/custom-llvm2/blob/master/include/llvm/DependencyInfo.h
115+
https://github.com/rollrat/custom-llvm2/blob/master/lib/Transforms/Scalar/Dependency.cpp
116+
```
117+
118+
The following link is the git link that developed the pass before creating the custom-llvm repository.
119+
```
120+
https://github.com/rollrat/llvm-control-pass
121+
```
122+
123+
### 2.1. Instruction Marking Type
124+
The following 4 items are marking type on Dependency Pass.
125+
```
126+
Annotated : Instruction to be substituted by StoreInst.
127+
Perpect : A fully connected Instruction.
128+
Dominated : Includes Perpect, and includes instructions to change the branch associated with the parent BasicBlock.
129+
Maybe : Dominated, and includes all instructions that change the branch of this BB with respect to all connected BasicBlocks.
130+
```
131+
`Annotated` >> `Perpect` >> `Dominated` >> `Maybe` Priority is determined in that order.
132+
For example, `Instruction` with `Annotated` marking includes `Maybe` marking.
133+
134+
### 2.2. Branch Map
135+
Branch Map is Control-Flow-Graph of Function BasicBlock. This is used to distinguish between Dominated and Maybe.
136+
Look up the Branch Map, use `Dominated` if one parent BasicBlock is one, or use `Maybe` if more than one.
137+
![Image](https://raw.githubusercontent.com/rollrat/custom-llvm2/master/cfg-type.png)
138+
139+
### 2.3. Function dependency
140+
An `Annotated` variable can be changed inside a called function if it is a pointer to a function's arguments.
141+
Also, if the return value of a function is `Dominated` by a variable that has been `Annotated`, the arguments of that function can affect the return value.
142+
To exploring these two things, we use the following classes to examine the call function.
143+
```
144+
FunctionReturnDependencyChecker: Checks which function arguments affect the return value.
145+
FunctionArgumentDependencyCheck: Checks which function arguments affect other function arguments.
146+
```
147+
If you need to check for function dependencies, use `run` function in` DependencyChecker` to check only once per function.
148+
This checking process is independent of whether or not `Annotate` is present.
149+
150+
### 2.4. Marking decision
151+
The followings are the classes and functions used for `Instruction` marking.
152+
``` c++
153+
class FunctionReturnDependencyChecker;
154+
class FunctionArgumentDependencyCheck
155+
class BottomUpDependencyChecker;
156+
```
157+
Only `BottomUpDependencyChecker` in the above class has `Instruction` marking privilege.
158+
```
159+
runPerpectBottomUp: Used on Perpect marking. (This function is called once per `Annotated` variable.)
160+
runBottomUp: Used on Dominated, Maybe marking.
161+
runSearch: Checks for changes in value by Store and function dependency. Used for `Annotated` marking with limited conditions.
162+
(This function conditionally calls runBottomUp.)
163+
processBranches: Use the Branch Map to conditionally call runSearch, runBottomUp.
164+
```
165+
![Image](https://raw.githubusercontent.com/rollrat/custom-llvm2/master/marking.png)
166+
167+
#### 2.4.1. runBottomUp Function
168+
`Instruction` through `runBottomUp` examines `Value` related to `Instruction` obtained through `getOperand`.
169+
`Dominated`, `Maybe` is marked, but marking distinction is not done in this function. Marking distinction through `processBranches`
170+
Is done.
171+
``` vb.net
172+
runBottomUp [Instruction: I, bool: P]
173+
if (P == true)
174+
I := Dominated
175+
else
176+
I := Maybe
177+
178+
for each Operand in I.getOperand
179+
runBottomUp(Operand, P)
180+
runSearch(Operand, P)
181+
182+
processBranches(I)
183+
```
184+
This iteration is repeated until the operand is not `Instruction`.
185+
If `Instruction` is` CallInst`, only function arguments with `ReturnDependency` are checked.
186+
187+
#### 2.4.2. runSearch Function
188+
`runSearch` checks for `Instruction` which is used as argument to `StoreInst` or` CallInst`.
189+
The `ROOT : bool` variable for `Annotated` marking is used, and this variable is only `true` in the call to marking `entry`.
190+
``` vb.net
191+
runSearch [Instruction: I, bool: P, bool: ROOT (= false)]
192+
for each Instruction in Function.BasicBlock
193+
if (type(Instruction) :: StoreInst)
194+
if (StoreInst.Pointer == I)
195+
if (ROOT == true)
196+
I := Annotated
197+
runPerpectBottomUp (StoreInst.Value)
198+
runBottomUp(StoreInst.Value, P && ROOT)
199+
runSearch(StoreInst.Value, P && ROOT)
200+
201+
else if (type(Instruction) :: CallInst)
202+
for each Oprand in FunctionArgumentDependency(CallInst.CalledFunction, Instruction.getOperand)
203+
runBottomUp(Operand, P && ROOT)
204+
runSearch(Operand, P && ROOT)
205+
206+
processBranches(I)
207+
```
208+
`P && ROOT` is exists, because we can not determine `Dominated`, `Maybe` at runSearch level.
209+
However, if `ROOT` is `true`, `P` is also` true` and subordinate `Instruction` is marked as `Dominated`.
210+
211+
#### 2.4.3. processBranches Function
212+
Using Branch Map, we tracks the Compare element that determines the branch.
213+
If the branch is not conditional, the compare element trace is skipped.
214+
``` vb.net
215+
processBranches [Instruction: I]
216+
processBlock(getNodeFromInstruction(I))
217+
218+
processBlock [BlockNode: BN]
219+
if (BN.getFromNodes.Size == 1)
220+
is_perpect := true
221+
else
222+
is_perepct := false
223+
224+
for each BlockNode in BN.getFromNodes
225+
if (BlockNode is Conditional)
226+
runBottomUp(BlockNode.getCondition, is_perpect)
227+
runSearch(BlockNode.getCondition, is_perpect)
228+
229+
processBlock(BlockNode)
230+
```
231+
The `BlockNode` once executed with `processBlock` will not be executed again.
232+
233+
#### 2.4.4. runPerpectBottomUp Function
234+
This function recursively traverses each Operand in `Instruction` to mark the `Perpect`.
235+
``` vb.net
236+
runPerpectBottomUp [Instruction: I]
237+
I := Perpect
238+
239+
for each Operand in I.getOperand
240+
runPerpectBottomUp(Operand)
241+
```
242+
243+
***
244+
245+
## 3. SelectionDAG Traking
246+
When the SelectionDAG is created, the `Instruction` Dependency information is passed to the DAGNode.
247+
The following procedure shows the code that the PassManager calls as it creates the SelectionDAG.
248+
```
249+
Reference: https://github.com/draperlaboratory/fracture/wiki/How-An-IR-Statement-Becomes-An-Instruction
250+
251+
FunctionPass
252+
-> MachineFunctionPass
253+
-> SelelctionDAGISel
254+
-> TargetDAGToDAGISel
255+
256+
include/llvm/Pass.h
257+
-> virtual bool runOnFunction(Function &F) = 0;
258+
259+
lib/CodeGen/MachineFunctionPass.cpp
260+
-> runOnMachineFunction(MF)
261+
262+
lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
263+
-> bool SelectionDAGISel::runOnMachineFunction(MachineFunction &mf)
264+
The runOnMachineFunction function runs Dependency Checking before the SelectAllBasicBlocks function is executed.
265+
266+
lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
267+
-> void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn)
268+
The SelectAllBasicBlocks function calls `FastISel` and` SelectBasicBlock`.
269+
`FastISel` is an InstructionSelection for debugging that runs only on -O0,
270+
`SelectBasicBlocks` generates a SelectionDAGNode by executing `DoInstructionSelection`.
271+
272+
lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
273+
-> void SelectionDAGISel::CodeGenAndEmitDAG() {
274+
In the CodeGenAndEmitDAG function, DAGCombine, DAGLegalize is executed.
275+
Instruction Schedule is also executed.
276+
```
277+
278+
***
279+
280+
## 4. Bugs
281+
The current version may not run the Dependency Pass for the following functions / functions, or an error may occur.
282+
```
283+
* Can not determine the ArgumentDependency of the function with the variable argument.
284+
```

FaultInjector.md

Whitespace-only changes.

0 commit comments

Comments
 (0)