This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH 0/3] Fix PR47654 and PR49649


On 07/18/2011 07:07 PM, Sebastian Pop wrote:
On Mon, Jul 18, 2011 at 11:11, Tobias Grosser<tobias@grosser.es> wrote:
We introduce casts when we generate code for an expression with a type
smaller than the types of its constituents.

So the next question is: What is the type of the expression. As far as I understand we decide ourselves which type the expression should have. Our correctness constraint is that the type must be large enough to contain [lb, ub] of the result as well as all operands. We can choose any larger type to reduce the number of casts that will generated.


Right, and so we cannot only rely on the lb_ub info, and we have to walk the CLAST expression and determine the largest type used as a we sub-expression: that's what gcc_type_for_clast_expr tries to do.
OK

Here is an example: supposing that we already code generated an IV
graphite_IV with a signed short type, then we are asked to generate
code for the expression "42 * graphite_IV", and finally suppose that
lb_ub returns the interval [-100, 100] for this expression, then we
would have a signed char type for the expression

So the signed char type is the smallest type we can use for the expression.


and so we would

introduce a cast of the graphite_IV to signed char before doing the
multiplication: so I guess the code generated for this expression
would be something like: "42 * (char) graphite_IV" of type char.
Without taking the max of the types of the sub-expressions, you would
have to generate casts for a shorter type.

Your example is a little incomplete, as 42 is missing a type. At the moment gcc_type_for_value() returns the smallest type that contains the scalar value. So I assume the type is a signed char.

If we choose for as type of the expression signed char we get this:
42 * (char) graphite_IV

On the other hand, if we choose signed short for the expression we get:
((short) 42) * graphite_IV


That would be just "42 * graphite_IV" of type short, as widening from char to short is possible without extra cast.
OK.

Both expressions contain a cast. Which one is better for the optimizer is
something I do not yet understand. However, I believe this choice is
basically a choice that can be taken locally for each expression. Using
either max(validy_type,(min(op1_type, op2_type, ...)) to favor small types
or max(validy_type,(max(op1_type, op2_type, ...)) to favor large types.

Can we find a solution that solves this problem more locally. I mean
instead
of using an imprecise algorithm that leads to larger types which
(accidentally?) leads to less casts, we could understand the type
calculated
by lb_ub_... as a minimal type needed for correctness. For each
instruction
that we code generate, we derive the type by electing a type that is
large
enough to be correct and that at the same time is not smaller than the
smallest type of each operand.


You surely mean "not smaller than the *largest* type of each operand".

No. As said above, both seem to be valid choices and this seems to be

Here is a counter-example where taking the type "not smaller than the smallest type of each operand" produces wrong code:

expression "a + b"
type of a is char
type of b is short
a goes from -100 to 100
b goes from 100 to 200

Computing the type of "a + b" as the type "not smaller than the
smallest type of each operand" leads to char.  Then, we would have to
generate the expression "(char) a + (char) b" of type char.  Casting
200 into a char overflows and is undefined.

You are right. In case we want to downcast b we would also need to prove that b itself fits into the smaller type. (This may happen, if the larger type was introduced earlier to remove casts, but is not needed to store the result). In most cases widening is probably easier.


I honestly do not like this function chain. The problem is that we would
calculate huge types, if we derive the type of an expression by only taking
into account the types of its sub(sub, ...) expressions. At the moment we do
not get these huge types, as our calculations are not 100% correct.

Lets assume we have a clast consisting of a single addition from several
integers.

127 + 127 + 127 + 127

Each integer would get the type signed char. Now the function
gcc_type_for_clast_red() would calculate the necessary type as max(char,
char, char, char) =>  char. However the correct type is actually max
(type([lb, ub]), min/max(char,char,char,char)). Where type([lb,ub]) =
type([508,508]) = short and the result is max(short, char) = short.


Right. We should be able to represent both the sub-expressions and their results in the computed type. The current implementation of gcc_type_for_clast_* is wrong.

gcc_type_for_clast_term () seems also to just use the type of the variable
instead of the type that would actually be needed to calculate<integer>  *
variable.

The types would become even larger as they would increase while walking up
the ClAST. This is because, we never take the actual ub,lb values into
account, but always derive the minimal type needed for correctness from the
types of the operands.

I believe, to derive correct types that are nor overly large, doing those
calculations locally would be better. For each expression we use ub/lb to
calculate the minimal type needed for correctness and then we choose a type
equal or larger than this type that minimizes the number of bad casts.

You would also need to make sure that every sub-expression can be expressed in that computed type: the example here is that of a min or a max expression of a loop bound: even if we know from the iteration domain that the IV belongs to [-128, 127] we cannot generate a char for this loop:

Sure. Only taking the lb/ub of the loop induction variable is not enough to derive a correct type for the whole clast. We need to get the right type for each subexpression.


for (i = -128; i< min (127, j + 200); i++)

we need a type large enough to be able to represent "j + 200", and
that would be short.  So we need to take again the "max of the types
of sub-expressions".

What is the "max of the types of sub-expressions"? Just the larges type is in general not large enough. a+b may not fit into the type of a nor in the type of b. However, assuming a and b may have any value that the types of a and b allow, would require us to assume a type that is definitely larger then the type of each argument (we do not do this, thats why some function are incorrect). Implementing this approach would yield to an explosion in type size.


What I propose is that you take advantage of your newly built lb/ub infrastructure and that we calculate for every subexpression the type as follows.

minimal_correct_type = max(min_type(lb_result, ub_result),
                           min_type(lb_op1, ub_op1),
                           min_type(lb_op2, ub_op2))

And then we choose a type that is equal or larger than minimal_correct_type and that reduces the number of introduced downcasts.

Cheers
Tobi



What we want is to get for each a single subexpression the types that







Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]