Forward propagation of expressions for single use variables.
Copyright (C) 2004-2024 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>.
This pass propagates the RHS of assignment statements into use
sites of the LHS of the assignment. It's basically a specialized
form of tree combination. It is hoped all of this can disappear
when we have a generalized tree combiner.
One class of common cases we handle is forward propagating a single use
variable into a COND_EXPR.
bb0:
x = a COND b;
if (x) goto ... else goto ...
Will be transformed into:
bb0:
if (a COND b) goto ... else goto ...
Similarly for the tests (x == 0), (x != 0), (x == 1) and (x != 1).
Or (assuming c1 and c2 are constants):
bb0:
x = a + c1;
if (x EQ/NEQ c2) goto ... else goto ...
Will be transformed into:
bb0:
if (a EQ/NEQ (c2 - c1)) goto ... else goto ...
Similarly for x = a - c1.
Or
bb0:
x = !a
if (x) goto ... else goto ...
Will be transformed into:
bb0:
if (a == 0) goto ... else goto ...
Similarly for the tests (x == 0), (x != 0), (x == 1) and (x != 1).
For these cases, we propagate A into all, possibly more than one,
COND_EXPRs that use X.
Or
bb0:
x = (typecast) a
if (x) goto ... else goto ...
Will be transformed into:
bb0:
if (a != 0) goto ... else goto ...
(Assuming a is an integral type and x is a boolean or x is an
integral and a is a boolean.)
Similarly for the tests (x == 0), (x != 0), (x == 1) and (x != 1).
For these cases, we propagate A into all, possibly more than one,
COND_EXPRs that use X.
In addition to eliminating the variable and the statement which assigns
a value to the variable, we may be able to later thread the jump without
adding insane complexity in the dominator optimizer.
Also note these transformations can cascade. We handle this by having
a worklist of COND_EXPR statements to examine. As we make a change to
a statement, we put it back on the worklist to examine on the next
iteration of the main loop.
A second class of propagation opportunities arises for ADDR_EXPR
nodes.
ptr = &x->y->z;
res = *ptr;
Will get turned into
res = x->y->z;
Or
ptr = (type1*)&type2var;
res = *ptr
Will get turned into (if type1 and type2 are the same size
and neither have volatile on them):
res = VIEW_CONVERT_EXPR<type1>(type2var)
Or
ptr = &x[0];
ptr2 = ptr + <constant>;
Will get turned into
ptr2 = &x[constant/elementsize];
Or
ptr = &x[0];
offset = index * element_size;
offset_p = (pointer) offset;
ptr2 = ptr + offset_p
Will get turned into:
ptr2 = &x[index];
Or
ssa = (int) decl
res = ssa & 1
Provided that decl has known alignment >= 2, will get turned into
res = 0
We also propagate casts into SWITCH_EXPR and COND_EXPR conditions to
allow us to remove the cast and {NOT_EXPR,NEG_EXPR} into a subsequent
{NOT_EXPR,NEG_EXPR}.
This will (of course) be extended as other needs arise.
Data structure that contains simplifiable vectorized permute sequences.
See recognise_vec_perm_simplify_seq () for a description of the sequence.