This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: USE patch vs the PA
- To: John Carr <jfc at tiac dot net>
- Subject: Re: USE patch vs the PA
- From: Jeffrey A Law <law at cygnus dot com>
- Date: Sat, 25 Oct 1997 11:16:43 -0600
- cc: egcs at cygnus dot com
- Reply-To: law at cygnus dot com
In message <199710251330.JAA02308@jfc.>you write:
>
> > > (1) R1 = constant
> > > (2) R2 = R1
> > > (3) R1 = variable
> > Note that if REG_N_SETS (R1) == 1, then find_base_value should return
> > reg_base_value [REGNO (R1)] if it is nonzero.
>
> Can you send me an example where this helps?
Not easily since the examples I'm working from sources with the
simplify_giv_expr patch, a rerun-loop patch, and other random
stuff I'm playing with.
It's worth noting that paying attention to REG_N_SETS and the
PLUS handling are closely related. It's not all that useful to
discuss one outside the context of the other.
Right now PLUS handling looks something like this:
case PLUS:
case MINUS:
{
rtx src_0 = XEXP (src, 0), src_1 = XEXP (src, 1);
/* Guess which operand is the base address.
If the first operand is a symbol or the second operand is
an integer, the first operand is the base address. Else if
either operand is a register marked as a pointer, it is the
base address. */
if (GET_CODE (src_1) == CONST_INT
|| GET_CODE (src_0) == SYMBOL_REF
|| GET_CODE (src_0) == LABEL_REF
|| GET_CODE (src_0) == CONST)
return find_base_value (src_0);
if (GET_CODE (src_0) == REG && REGNO_POINTER_FLAG (REGNO (src_0)))
return find_base_value (src_0);
if (GET_CODE (src_1) == REG && REGNO_POINTER_FLAG (REGNO (src_1)))
return find_base_value (src_1);
return 0;
}
So, if you have (plus (reg) (reg)) and neither has REGNO_POINTER_FLAG
set we do nothing. Even if one of the regs has a known base value.
One might think that one of the regs should have REGNO_POINTER_FLAG set.
* Conceptually REGNO_POINTER_FLAG should only be set for a "pure
pointer". By pure pointer I mean the value in the reg must be
within the object being pointed to.
That sounds odd, but gcc will internally often create a pseudoreg
outside the bounds of an object, then "correct" it with a later
addition. The pseudo which is out of the bounds of the object
must not have REGNO_POINTER_FLAG set.
Thus, if you have (set (regC) (plus (regA) (regB))) and regA has
REGNO_POINTER_FLAG set, you can _not_ set REGNO_POINTER_FLAG for
regC unless you can prove that the sum of (regA) (regB) still
points within the same object as (regA).
It is important to realize that for alias gathering you only
care about relating values to some base value (ie a symbol_ref,
frame_pointer_rtx, etc).
* On a technical level consider a call to emit_iv_add_mult.
It basically computes b * m + a.
In one case I care about it computes:
(plus (mult (reg 101) (const_int 8))
(plus (plus (reg 975) (const_int -8))
(reg 1024))
[ That's not canonicalized, but you get the idea... ]
Which (of course) creates multiple insns, with temporary
pseudos holding some values -- we can't get at those pseudos
easily to propagate REGNO_POINTER_FLAG the way we might want to.
Furthermore, even though (reg 1024) is the pointer, it is
difficult to prove that any subexpression involving reg 1024
is a pointer.
So, how does the PLUS handling tie into peeking at REG_N_SETS?
Basically at the top of the PLUS/MINUS code in find_base_value my
code does something like this:
if (GET_CODE (src_0) == REG)
{
temp = find_base_value (src_0);
if (temp)
src_0 = temp;
}
if (GET_CODE (src_1) == REG)
{
temp = find_base_value (src_1);
if (temp)
src_1 = temp;
}
Which will allow us to pick up any underlying information about
the two regs, regardless of whether or not one is a strict pointer.
Using the example above we might emit code like:
(set (temp1) (plus (reg 975) (const_int -8)))
(set (temp2) (plus (reg 1024) (temp1)))
(set (temp3) (plus (mult (reg 101) (const_int 8)) (temp2)))
Remember (reg 1024) is related to a SYMBOL_REF.
So consider what happens when we find the set for temp2.
find_base_value is called with (plus (reg 1024) (temp1))
(reg 1024) is a pointer, so we call find_base_value (reg 1024), but
since find_base_value just returns the original reg we get nothing
useful back.
If we change find_base_value to return reg_base_values[X] if
the register is only set once, then we can relate temp2 back to
the SYMBOL_REF (via reg 1024).
That's the first improvement, we've now propagated the base value
to one more register.
Then consider what happens for temp3. We call into find_base_value
with (plus (mult (reg 101) (const_int 8)) (temp2)))
temp2 does not have REGNO_POINTER_FLAG set, so we basically do
nothing and are unable to relate temp3 back to the SYMBOL_REF
(via temp2 & (reg 1024)).
With my change we call find_base_value on temp2, which will give
us back the SYMBOL_REF. This allows us to relate temp3 back to the
original SYMBOL_REF (via temp2 & (reg 1024).
jeff