SPO600 Project Stage 2 (Pt.6) - Testing in AArch64 and Reflection

In the previous parts, I created a GCC pass on an x86-64 server to identify function clones and compare them. 

Testing in AArch64 Server

Source code is the same as the one posted in part 5.

Source code and critical files for both servers are also available in GitHub.


When I compile, there is a warning " Function Multi Versioning support is experimental." 
That's exactly what I am doing.


[jyau11@aarch64-002 test-clone]$  make CC=/home/jyau11/spo600/lab4/gcc-test-003/bin/gcc DUMP_ALL=1
/home/jyau11/spo600/lab4/gcc-test-003/bin/gcc -c  vol_createsample.c -o vol_createsample.o
/home/jyau11/spo600/lab4/gcc-test-003/bin/gcc -D 'CLONE_ATTRIBUTE=__attribute__((target_clones("default","rng") ))'\
        -march=armv8-a -g -O3 -fno-lto  -ftree-vectorize  -fdump-tree-all -fdump-ipa-all -fdump-rtl-all \
        clone-test-core.c vol_createsample.o -o clone-test-aarch64-prune
clone-test-core.c:28:6: warning: Function Multi Versioning support is experimental, and the behavior is likely to change [-Wexperimental-fmv-target]
   28 | void scale_samples(int16_t *in, int16_t *out, int cnt, int volume) {
      |      ^~~~~~~~~~~~~
/home/jyau11/spo600/lab4/gcc-test-003/bin/gcc -D 'CLONE_ATTRIBUTE=__attribute__((target_clones("default","sve2") ))' \
        -march=armv8-a -g -O3 -fno-lto  -ftree-vectorize  -fdump-tree-all -fdump-ipa-all -fdump-rtl-all \
        clone-test-core.c vol_createsample.o -o clone-test-aarch64-noprune
clone-test-core.c:28:6: warning: Function Multi Versioning support is experimental, and the behavior is likely to change [-Wexperimental-fmv-target]
   28 | void scale_samples(int16_t *in, int16_t *out, int cnt, int volume) {
      |      ^~~~~~~~~~~~~

As expected, the pass can work on AArch64 server. The output is correct. 
NOPRUNE for the noprune-test-case
PRUNE for the prune-test-case


Reflection

Pass limitation and capabilities :

First, my pass only works with the GIMPLE intermediate representation and only analyzes C programs. It does not modify or optimize the program in any way. It processes every function regardless of whether it is ever called. The purpose of the pass is to determine whether a clone can be pruned, so it uses dump_file to output the results and only operates on functions that have a body.

The pass only handles the first cloned function. It works best when there are exactly two clones of a function. If there are more than two clones, say, clones A, B, and C, where A is the first, both B and C will be compared with A to determine whether they are the same as A. However, if A != (B = C), the pass will still report "NOPRUNE", even though one of B or C could potentially be pruned.

Regarding variable comparison, the pass only processes Gimple statements of types: GIMPLE_ASSIGN, GIMPLE_COND, and GIMPLE_DEBUG. It may not behave correctly if other types of GIMPLE statements appear. However, I have verified that the test case examples only include these three types, along with GIMPLE_RETURN.

The pass is able to compare two clones based on the total number of basic blocks and Gimple statements. It then compares the types of Gimple statements. If a statement is an assignment, it compares the operands on the right-hand side. Finally, it compares the appearance pattern of variables in GIMPLE statements of the following types of GIMPLE_ASSIGN, GIMPLE_COND, and GIMPLE_DEBUG_BIND.

What I have learn:

Throughout this project, I’ve learned a lot. This includes understanding how the execute function works for each pass, what call graph node is, what Gimple types are, how to extract variables from Gimple statements, how to compare them, and what exactly needs to be compared, etc. 

The most challenging part was not knowing how the execute function and cgraph_node work or how they are related to each other. I initially tried to store the nodes or function pointers in a static variable so I could use them to compare with the next node/function in the next execution call. It turned out to be a complete failure, and I had to rewrite the pass using a different approach. Although I spent a lot of time on this, I learned a great deal.

Whenever I encountered a gap in my knowledge, I re-watched lecture recordings, tested code through trial and error, wrote small programs to observe how things worked, and read online documentation/other passes. Once I cleared up the concepts, the most enjoyable part for me was writing the C/C++ code.

Future Improvement

For project Stage 3, I may wish to extend variable checking for other type of Gimple statements. Also, I am also thinking of how can I directly compare the statements of two clones instead of using static variable to store them.



Comments

Popular posts from this blog

SPO600 Project Stage 1 (Pt.1) - Create a GCC Pass

SPO600 Project Stage 3 - Identify clones of multiple functions and compare them

SPO600 Project Stage 2 (Pt.1) - GCC pass locating clone function