I have some legacy code to understand and I stumbled upon the fact that inside the code the same struct is being accessed very very often. Would it make any difference if I save the content of the struct beforehand and then access the local copy instead of accessing through the pointer?
I already compared some testcode via a online assembler to see if it would optimize the code. Done that with https://godbolt.org/ ARM64 gcc8.2
Variant A
typedef struct STRUCT_D{ int myInt1IND; int myInt2IND; int myInt3IND; int myInt4IND; int myInt5IND; int myInt6IND; int myInt7IND; int myInt8IND; int myInt9IND; } STRUCT_D; typedef struct STRUCT_C{ STRUCT_D myStructInDIntINC; } STRUCT_C; typedef struct STRUCT_B{ STRUCT_C * myPointerB; } STRUCT_B; typedef struct STRUCT_A{ STRUCT_B * myPointerA; } STRUCT_A; int square(void) { struct STRUCT_C myStructC; struct STRUCT_B myStructB; struct STRUCT_A myStructA; struct STRUCT_A* startPointer; myStructC.myStructInDIntINC.myInt1IND = 55; myStructB.myPointerB = &myStructC; myStructA.myPointerA = &myStructB; startPointer = &myStructA; int myresult = startPointer->myPointerA->myPointerB->myStructInDIntINC.myInt1IND + startPointer->myPointerA->myPointerB->myStructInDIntINC.myInt2IND + startPointer->myPointerA->myPointerB->myStructInDIntINC.myInt3IND + startPointer->myPointerA->myPointerB->myStructInDIntINC.myInt4IND + startPointer->myPointerA->myPointerB->myStructInDIntINC.myInt5IND + startPointer->myPointerA->myPointerB->myStructInDIntINC.myInt6IND + startPointer->myPointerA->myPointerB->myStructInDIntINC.myInt7IND + startPointer->myPointerA->myPointerB->myStructInDIntINC.myInt8IND + startPointer->myPointerA->myPointerB->myStructInDIntINC.myInt9IND; return myresult; } Variant B
typedef struct STRUCT_D{ int myInt1IND; int myInt2IND; int myInt3IND; int myInt4IND; int myInt5IND; int myInt6IND; int myInt7IND; int myInt8IND; int myInt9IND; } STRUCT_D; typedef struct STRUCT_C{ STRUCT_D myStructInDIntINC; } STRUCT_C; typedef struct STRUCT_B{ STRUCT_C * myPointerB; } STRUCT_B; typedef struct STRUCT_A{ STRUCT_B * myPointerA; } STRUCT_A; int square(void) { struct STRUCT_C myStructC; struct STRUCT_B myStructB; struct STRUCT_A myStructA; struct STRUCT_A* startPointer; myStructC.myStructInDIntINC.myInt1IND = 55; myStructB.myPointerB = &myStructC; myStructA.myPointerA = &myStructB; startPointer = &myStructA; struct STRUCT_D myResultStruct = startPointer->myPointerA->myPointerB->myStructInDIntINC; int myresult = myResultStruct.myInt1IND + myResultStruct.myInt2IND + myResultStruct.myInt3IND + myResultStruct.myInt4IND + myResultStruct.myInt5IND + myResultStruct.myInt6IND + myResultStruct.myInt7IND + myResultStruct.myInt8IND + myResultStruct.myInt9IND; return myresult; } I know that STRUCT_D is not fully initialized, but is for this example not relevant. My question would be if variant B is "better". Of course it is better readable, but does it make sense to save the context of a pointer. As I said in my file the same pointer is being dereferenced approximately 150 times in the same function. I know I know.. This function should definitely be refactored. :D
struct STRUCT_D *myResultStruct = &startPointer->myPointerA->myPointerB->myStructInDIntINC;andint myresult = myResultStruct->myInt1IND + myResultStruct->myInt2IND + .... Just to give the compiler a helping hand (if it fails to optimize the code) and save typing.