On 07/04/2020 14:34, Michael Matz wrote:
Hello,
On Tue, 7 Apr 2020, Erick Ochoa wrote:
Thanks for this lead! It is almost exactly what I need. I do have one more
question about this. It seems that the types obtained via
FOR_EACH_FUNCTION_ARGS and TREE_TYPE are different pointers when compiled with
-flto.
What do I mean by this? Consider the following code:
#include <stdio.h>
int main(){
FILE *f = fopen("hello.txt", "w");
fclose(f);
return 0;
}
The trees corresponding to types FILE* and FILE obtained via the variable f
are different from the trees obtained from the argument to fclose.
Yes, quite possible.
However, when we are compiling the simple C program via
/path/to/gcc -flto a.c -fdump-ipa-hello-world -fipa-hello-world
/path/to/gcc -flto -flto-patition=none -fipa-hello-world a.c -o a.out
one can see that the pointers are different:
pointers 0xffff79ee1c38 =?= 0xffff79ee0b28
records 0xffff79ee1b90 =?= 0xffff79ee0a80
Do you, or anyone else for that matter, know if it would be possible to
keep the trees pointing to the same address? Or, in case it can be
possible with some modifications, where could I start looking to modify
the source code to make these addresses match? The other alternative for
me would be to make my own type comparison function, which is something
I can do. But I was wondering about this first.
So, generally type equality can't be established by pointer equality in
GCC, even more so with LTO; there are various reasons why the "same" type
(same as in language equality) is represented by different trees, and
those reasons are amplified with LTO. We try to unify some equal types to
the same trees when reading in LTO bytecode, but that's only an
optimization mostly.
So, when you want to compare types use useless_type_conversion_p (for
equivalence you need useless(a,b) && useless(b,a)). In particular, for
record types T it's TYPE_CANONICAL(T) that needs to be pointer-equal.
(I.e. you could hard-code that as well, but it's probably better to use
the existing predicates we have). Note that useless_type_conversion_p is
for the middle-end type system (it's actually one part of the definition
of that type system), i.e. it's language agnostic. If you need language
specific equality you would have to use a different approach, but given
that you're adding IPA passes you probably don't worry about that.
I've been using TYPE_MAIN_VARIANT(T) as opposed to TYPE_CANONICAL(T).
This was per the e-mail thread:
https://gcc.gnu.org/legacy-ml/gcc/2020-01/msg00077.html .
I am not 100% sure what the differences are between these two yet, but I
think TYPE_CANONICAL(T) was not helpful because of typedefs? I might be
wrong here, it has been a while since I did the test to see what worked.
Using TYPE_MAIN_VARIANT(T) has gotten us far in an optimization we are
working on, but I do think that a custom type comparison is needed now.
I do not believe I can use useless_type_conversion_p because I need a
partial order in order to place types in a set.
Ciao,
Michael.