I'm trying to write a pass in gcc to implementing structure splitting. And I'm having a problem that I don't know how to locate the gimple that I want and I need to change it of course.
This is the origin C code and the gimple:
struct node {
float _Complex al;
unsigned long long state;
};
struct reg {
int size;
struct node *node;
};
// example function
void func(int c1, int c2, int target, struct reg* r) {
for (int i = 0; i < r->size; i++) {
if (c1) {
r->node[i].state += 3;
}
}
}
void func (int c1, int c2, int target, struct reg * r)
{
{
int i;
i = 0;
goto <D.2885>;
<D.2884>:
if (c1 != 0) goto <D.2895>; else goto <D.2896>;
<D.2895>:
_1 = r->node;
_2 = (long unsigned int) i;
_3 = _2 * 16;
_4 = _1 + _3;
_5 = _4->state;
_6 = r->node;
// ...
}
}
And Here's C code and gimple that I want to change to:
struct node {
float _Complex *al; // changed
unsigned long long *state; // changed
};
struct reg {
int size;
struct node *node;
};
void func(int c1, int c2, int target, struct reg* r) {
for (int i = 0; i < r->size; i++) {
if (c1) {
r->node->state[i] += 3; // changed
}
}
}
void func (int c1, int c2, int target, struct reg * r)
{
{
int i;
i = 0;
goto <D.2884>;
<D.2883>:
if (c1 != 0) goto <D.2894>; else goto <D.2895>;
<D.2894>:
_1 = r->node;
_2 = _1->state;
_3 = (long unsigned int) i;
_4 = _3 * 8;
_5 = _2 + _4;
_6 = *_5;
_7 = r->node;
// ...
}
}
And I put my pass at ipa-late-pass and declared it as a SIMPLE_IPA_PASS. Here is my code in the pass:
unsigned int
pass_struct_split::execute (function *)
{
// 1. get desire struct type
tree desire_type = get_split_types(); // `struct node`
if (!desire_type) return 0;
// 2. find the struct type and split it
struct cgraph_node *node;
FOR_EACH_DEFINED_FUNCTION(node) {
printf("===start func===\n");
struct function *func = DECL_STRUCT_FUNCTION (node->decl);
basic_block bb;
FOR_EACH_BB_FN (bb, func) {
gimple_stmt_iterator start, end;
for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) {
gimple *stmt = gsi_stmt (gsi);
// find xx = r->node
if (gimple_code(stmt) == GIMPLE_ASSIGN) {
if (gimple_assign_rhs_code(stmt) == COMPONENT_REF) {
tree lhsop = gimple_assign_lhs (stmt);
tree rhsop = gimple_assign_rhs1 (stmt);
if (TREE_CODE(TREE_TYPE(rhsop)) == POINTER_TYPE && TREE_CODE(TREE_TYPE(TREE_TYPE(rhsop))) == RECORD_TYPE) {
tree pointee_type = TREE_TYPE(TREE_TYPE(rhsop));
if (pointee_type == desire_type) {
// record start
start = gsi;
}
}
}
}
// find the end place: find xx = xx->state
}
}
}
return 0;
}
I can't locate the r->node[i].state parts. I only get the start point which I don't know if it's the right way to record the start point. And I'm stucked with locating the end point. And this is just an ASSIGN statement. I'm not sure if I can handle other kind of statements like malloc and some tricky ones. So how can I locate it? Or is there a better way or some interfaces to make it work?
Thanks for your help!