Is there any way to get an lli execution trace. As an example for a given program:
define dso_local i32 #main() {
%1 = alloca i32, align 4
store i32 1, i32* %1, align 4
%2 = load i32, i32* %1, align 4
ret i32 %2
}
I would like to have some runtime output like:
$ lli test.ll -trace
%1 = alloca(4)
st %1, 1 ; [%1] = 1
ld %1 -> %2 ; %2 = 1
ret %2 ; ret 1
I've found an XRay project but it seems to be complicated. Are there any llc native ways to output execution trace?
I didn't find one, and ended up writing something that's general enough for my needs but not even nearly appropriate for general use. One big problem is that any code can call native code, and most code does that very often, so the tracer only traces a few instructions before encountering a CallInst it cannot handle.
If you're only interested in very short instruction sequences, the functions in Analysis/ConstantFolding.h may be helpful... or may not, it depends on your purpose. If you have to write a tracer yourself, you might want to look around for code that uses InstVisitor, some of that code may be usable, reusable, or a good starting point. Good luck.
Related
i have this code:
int main() {
int i = 0;
int &j = i;
j = 10;
return i;
}
and after pass -mem2reg, get the ir as follows:
define dso_local i32 #main() #0 !dbg !7 {
entry:
call void #llvm.dbg.value(metadata i32 0, metadata !11, metadata !DIExpression()), !dbg !12
call void #llvm.dbg.value(metadata i32* undef, metadata !13, metadata !DIExpression()), !dbg !12
call void #llvm.dbg.value(metadata i32 10, metadata !11, metadata !DIExpression()), !dbg !12
ret i32 10, !dbg !15
}
What I'm confused about is what analysis LLVM uses to get i and j to be equivalent.
I got the details of this pass runtime:
[2021-12-02 11:53:05.295018000] 0x5626d58d2a20 Executing Pass 'Function Pass Manager' on Module '/usr/local/LLVM/test/e0.ll'...
[2021-12-02 11:53:05.295137300] 0x5626d58bf890 Executing Pass 'Dominator Tree Construction' on Function 'main'...
[2021-12-02 11:53:05.295169500] 0x5626d58bf890 Executing Pass 'Promote Memory to Register' on Function 'main'...
0x5626d58bf330 Required Analyses: Assumption Cache Tracker, Dominator Tree Construction
[2021-12-02 11:53:05.295364900] 0x5626d58bf890 Made Modification 'Promote Memory to Register' on Function 'main'...
0x5626d58bf330 Preserved Analyses: Natural Loop Information, Lazy Branch Probability Analysis, Lazy Block Frequency Analysis, Interval Partition Construction, Post-Dominator Tree Construction, Machine Dominance Frontier Construction, MachineDominator Tree Construction, WebAssembly Exception Information, Spill Code Placement Analysis, Bundle Machine CFG Edges, Machine Natural Loop Construction, Detect single entry single exit regions, Dominance Frontier Construction, View regions of function, Print regions of function to 'dot' file, View regions of function (with no function bodies), MachinePostDominator Tree Construction, Delinearization, Print regions of function to 'dot' file (with no function bodies), Detect single entry single exit regions, Dependence Analysis, Dominator Tree Construction, Dominator Info Printer, Print a call graph, Lazy Machine Block Frequency Analysis, Analysis if a function is memory bound, Strip gc.relocates inserted through RewriteStatepointsForGC, Machine Block Frequency Analysis, Block Frequency Analysis, Basic Alias Analysis (stateless AA impl)
-*- 'Promote Memory to Register' is the last user of following pass instances. Free these instances
[2021-12-02 11:53:05.295628600] 0x5626d58bf890 Freeing Pass 'Dominator Tree Construction' on Function 'main'...
[2021-12-02 11:53:05.295648400] 0x5626d58bf890 Freeing Pass 'Promote Memory to Register' on Function 'main'...
[2021-12-02 11:53:05.295663100] 0x5626d58bf890 Executing Pass 'Module Verifier' on Function 'main'...
-*- 'Module Verifier' is the last user of following pass instances. Free these instances
[2021-12-02 11:53:05.295725200] 0x5626d58bf890 Freeing Pass 'Module Verifier' on Function 'main'...
[2021-12-02 11:53:05.295740400] 0x5626d58d2a20 Made Modification 'Function Pass Manager' on Module '/usr/local/LLVM/test/e0.ll'...
-*- 'Function Pass Manager' is the last user of following pass instances. Free these instances
[2021-12-02 11:53:05.295828100] 0x5626d58d2a20 Freeing Pass 'Assumption Cache Tracker' on Module '/usr/local/LLVM/test/e0.ll'...
[2021-12-02 11:53:05.295850400] 0x5626d58d2a20 Executing Pass 'Print Module IR' on Module '/usr/local/LLVM/test/e0.ll'...
-*- 'Print Module IR' is the last user of following pass instances. Free these instances
[2021-12-02 11:53:05.299496500] 0x5626d58d2a20 Freeing Pass 'Print Module IR' on Module '/usr/local/LLVM/test/e0.ll'...
Can someone help me figure out which analysis or optimization lets LLVM know that i and j are equivalent,very thankful!
Generate unoptimized IR with clang
clang -S -emit-llvm -Xclang -disable-O0-optnone xx.cpp
Optimize the resulting IR with opt
opt --print-after-all -O3 xx.ll -S -o yy.ll
If you look at the IR as it gets optimized you'll see it gets simplified in the SimplifyCFGPass.
For example, the code below
%div = sdiv i32 %add, %36
%38 = trunc i64 %indvars.iv.next18 to i32
%mul11 = mul nsw i32 %div, %38
The fist and third instruction may be a data dependency because the first instruction computes %div and the third one need %div.
Similarly, %38 computed at second instruction, and the third instruction needs it.
Are there any tools or llvm opt commands can get the information about data dependency?
I tried opt -enable-new-pm=0 -da -stats source_ir.ll but nothing will print out.
Sorry for such a noob question, but why the result is not 516?
define i32 #main()
{
%1 = add i32 6, 500
%2 = add i32 5, 5
%3 = add i32 %1, %2
ret i32 %3
}
http://llvm.org/docs/LangRef.html#integer-type
i32 a 32-bit integer.
Usage:
./lli Program.ir; echo $?
4
Thanks in advance
The exit code of a process in Unix is only 8 bits. Any larger value gets truncated, regardless of whether LLVM is involved:
$ ( exit 516 ); echo $?
4
The exit code (I'm going to distinguish the exit value returned by your program, from the exit code made available to the process that started you program) is actually, in UNIX like operating systems, a conglomeration of several different items, one of which is the exit value. See, for example, this link, which contains (with my emphasis and [extra information]):
Don't confuse a program's exit status [value] with a process' termination status [code]. There are lots of ways a process can terminate besides having its program finish. In the event that the process termination is caused by program termination (i.e., exit), though, the program’s exit status [value] becomes part of the process' termination status [code].
The macro to get the actual exit status from the process (see here) states:
If WIFEXITED is true of status, this macro returns the low-order 8 bits of the exit status value from the child process.
That's also indicated by the actual source code of the Linux exit_group syscall, which is the one eventually called by exit:
SYSCALL_DEFINE1(exit_group, int, error_code)
{
do_group_exit((error_code & 0xff) << 8);
/* NOTREACHED */
return 0;
}
You can see there that it only uses the lower eight bits of the exit value, and shifts it left so it can store those other items (control information) in there, all zero in this case. Contrast that with the same call from the signal processor which only sets the control information:
do_group_exit(ksig->info.si_signo)
In other words, it also has to put other things in the process exit code, such as which signal terminated it (if it was terminated by a signal), whether it dumped core, and so on. That's why the exit value is limited to a lesser range than you expect.
The ISO standard (C11) also allows for this, in 7.22.4.4 The exit function /5 (since returning an integer value from main() is equivalent to calling exit() with that value:
Finally, control is returned to the host environment. If the value of status is zero or EXIT_SUCCESS, an implementation-defined form of the status successful termination is returned. If the value of status is EXIT_FAILURE, an implementation-defined form of the status unsuccessful termination is returned. Otherwise the status returned is implementation-defined.
Is it possible to use the comments in IR in my pass? Basically I want to use the IR annotated with basic block frequency, which is written in comments, as shown below, and I need the frequency value in my pass. I know this is naive method, but it will suffice.
define internal void #MDFilter() #0 {
entry:
;;; Basic block executed 2 times. <-- I NEED THIS COMMENT AS A STRING IN MY PASS
%mdContext = alloca %struct.MD5_CTX, align 8
%bytes = alloca i32, align 4
%data = alloca [16 x i8], align 16
call void #MD5Init(%struct.MD5_CTX* %mdContext)
br label %while.cond
;;; Out-edge counts: [2.000000e+00 -> while.cond]
Any other method to obtain this info is also welcome.
No, there is no way to use the comments' contents this way, not without significantly changing the IR parser. However, there's no need to re-invent the wheel; there's a mechanism in LLVM which is intended precisely for these sorts of things - transferring information from the front-end into an LLVM pass - and that is metadata.
So whatever or whoever is adding this information to the IR should add it with metadata instead - see these sources for more information on how to do that:
http://llvm.org/docs/LangRef.html#metadata
http://llvm.org/docs/LangRef.html#named-metadata
Adding Metadata to Instructions in LLVM IR
How to attach metadata to LLVM IR using the C++ API?
How to add a Metadata String to an LLVM module with the C++ API?
If you have no control over the generation of data, then you should add some pre-processing step in which you convert the comments to metadata.
In the end the IR should look something like:
define internal void #MDFilter() #0 {
entry:
%mdContext = alloca %struct.MD5_CTX, align 8, !freq !1
%bytes = alloca i32, align 4
%data = alloca [16 x i8], align 16
call void #MD5Init(%struct.MD5_CTX* %mdContext)
br label %while.cond, !outedge !2
...
!1 = metadata !{i32 2}
!2 = metadata !{float 2.0}
And your pass needs to look for these !freq and !outedge nodes.
I followed the How to get variable definition line number etc. using dbg metadata? in order to get the line number definition for local variables (allocas), which works fine. But I need the same for globals. So I tried to hack the findDbgGlobalDeclare() method from http://llvm.org/docs/doxygen/html/DbgInfoPrinter_8cpp_source.html#l00062 . However, I have no llvm.dbg.gv in my bytecode, so there is no dbg info to extract. I compile my target code using clang++ -O0 -g -emit-llvm Test.cpp -c -o Test.bc . Some samples from my bytecode:
#r = global i32 3, align 4
%4 = load i32* #r, align 4, !dbg !942
...
%a = alloca i32, align 4
%1 = load i32* %a, align 4, !dbg !939
However, I do have:
!924 = metadata !{i32 786484, i32 0, null, metadata !"r", metadata !"r", metadata !"", metadata !841, i32 19, metadata !56, i32 0, i32 1, i32* #r} ; [ DW_TAG_variable ] [r] [line 19] [def]
with on which !0 is indirectly dependent and there is !llvm.dbg.cu = !{!0} .
Thank you !
Yes, !llvm.dbg.cu is the right place now. Quoting from the source-level debugging document:
Compile unit descriptors provide the root context for objects declared
in a specific compilation unit. File descriptors are defined using
this context. These descriptors are collected by a named metadata
!llvm.dbg.cu. They keep track of subprograms, global variables and
type information.
Specifically, see "Global variable descriptors".
The code you found is to support the older metadata nodes which are still generated by dragonegg so the readers support them for backwards compatibility. New LLVM code generates !llvm.dbg.cu.
The steps are as follows:
1. NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.cu");
Then get into the metadata nodes chain till the desired global declaration.
2. DIDescriptor DIG(cast<MDNode>(NMD->getOperand(i)));
3. DIDescriptor DIGG(cast<MDNode>(NMD->getOperand(NMD->getNumOperands()-1)));
4. DIDescriptor DIGF(cast<MDNode>(DIGG->getOperand(0)));
5. Value* VV = cast<Value>(DIGF->getOperand(i));
6. DIDescriptor DIGS(cast<MDNode>(VV));
At this point, do:
7. DIGS->getOperand(j)
and check http://llvm.org/docs/SourceLevelDebugging.html#c-c-front-end-specific-debug-information for all the fields you desire.