Project Stage 2 - (Implementation)

In this blog post, I'll delve into the detailed implementation of a new pass named "prune_clones" in GCC. This pass aims to traverse the call graph and prune duplicate clones, enhancing optimization capabilities within the compiler.

Introduction

In previous discussions, I outlined a plan to integrate a new pass into GCC for optimizing clone functions. Here, I will focus on the concrete implementation details, showcasing how this pass is structured and integrated into GCC's build process.

1. Create the New Pass File:

First, create the new source file 'prune-clones.cc' in the GCC source directory.

[sshin36@aarch64-001 gcc]$ touch prune-clones.cc


2. Write the Code for the New Pass:


Define the Pass Data Structure:

create the pass data structure to define the properties of new pass

#include "cgraph.h"

#include "tree-pass.h"


// Define the pass data structure

const pass_data pass_data_prune_clones = {

    GIMPLE_PASS,         // type

    "prune_clones", // name

    OPTGROUP_NONE, // optinfo_flags

    TV_NONE,             // tv_id

    0,                   // properties_required

    0,                   // properties_provided

    0,                   // properties_destroyed

    0,                   // todo_flags_start

    0                    // todo_flags_finish

};


Define the Pass Class:

define the pass class that inherits from 'gimple_opt_pass'.


// Define the pass class

class pass_prune_clones : public gimple_opt_pass {

public:

    pass_prune_clones(gcc::context *ctxt)

        : gimple_opt_pass(pass_data_prune_clones, ctxt) {}


    unsigned int execute(function *fun) final override;


}; 


Implement the Execute Function

Implement the execute function that traverses the call graph and prunes duplicate clones.


// Execute function for the pass

unsigned int pass_prune_clones::execute(function *fun) {

    // Walk each function in the call graph

    FOR_EACH_FUNCTION(node) {

        // If node points to SIMD clones

        if (node->simd_clones) {

            prune_clones(node);

        }

    }

    return 0;

}


Implement the Pruning Function

define the 'prune_clones' function to handle the actual pruning logic.


// Function to prune duplicate clones

unsigned int prune_clones(cgraph_node *node) {

    cgraph_function_version_info *default_fvi = node->function_version();

    cgraph_function_version_info *curr_fvi = node->function_version();

    

    while (curr_fvi->next) {

        // Get the next clone

        curr_fvi = curr_fvi->next;

        // Compare to the default node

        // Prune if duplicate

    }

    

    return 0;

}


Create a Function to Instantiate the Pass

create a helper function to instantiate the pass.


// Function to create a new instance of the gimple_opt_pass

gimple_opt_pass *make_pass_prune_clones(gcc::context *ctxt) {

    return new pass_prune_clones(ctxt);

}


3. Schedule the New Pass in 'passes.def':

Add new pass to the pass scheduling file passes.def.

  NEXT_PASS (pass_data_prund_clones);



4. Modify Makefile.in:
Update 'Makefile.in' to include the new source file 'prune-clones.cc' in the build process

Add the Object File
Add `prune-clones.o' to the 'OBJS' list.
OBJS = ... \
       prune-clones.o \
       ...

Add the Source File
Add `prune-clones.cc' to the list of sources files.
GTFILES = $(srcdir)/existing-file.cc \
          $(srcdir)/prune-clones.cc \
          ...

5. Update 'gcc/gcc.cc':

Include new pass header and register the pass in the main function

Include the Header
include the header file for the new pass.

#include "prune-clones.h"


Register the Pass
register the pass in the 'driver::main' function.

int

driver::main (int argc, char **argv)

{

  bool early_exit;


  g->add_pass(make_pass_prune_clones(ctxt));

  set_progname (argv[0]);

  expand_at_files (&argc, &argv);

Conclusion

In this blog post, I've implemented the prune_clones pass in GCC, enhancing its optimization capabilities by effectively managing clone functions. I covered the coding aspects of defining the pass, integrating it into GCC's build system, and registering it in the main GCC executable. It still needs to be improved further more. You can check improvements of pruning clones pass at my GitHub repo below.

Github Repo:



댓글

이 블로그의 인기 게시물

Lab 1 - Calculate performance & memory usage

Project Stage - 1 GCC for AArch64

Project stage-3 (testing & reflection)