Ajit Agarwal <[email protected]> writes:
> Hello Richard:
>
> On 15/08/24 3:45 pm, Richard Sandiford wrote:
>> Ajit Agarwal <[email protected]> writes:
>>> +static void
>>> +update_change (set_info *set)
>>> +{
>>> + if (!set->has_any_uses ())
>>> + return;
>>> +
>>> + auto *use = *set->all_uses ().begin ();
>>> + do
>>> + {
>>> + auto *next_use = use->next_use ();
>>> + if (use->is_in_debug_insn ())
>>> + substitute_debug_use (use);
>>> + else if (use->is_in_phi ())
>>> + {
>>> + update_change (use->phi ());
>>> + }
>>> + else
>>> + {
>>> + crtl->ssa->remove_use (use);
>>> + }
>>> + use = next_use;
>>> + }
>>> + while (use);
>>> +}
>>
>> This still contains direct modifications to the rtl-ssa ir (remove_use).
>> Which case is it handling? REG_EQUAL notes?
>>
>
> This is done to handle your below comments:
>
> Thanks. It looks like you're updating just the definitions,
> and then later updating the uses. That isn't the way that rtl-ssa
> is supposed to be used. Each change set -- in other words, each call
> to function_info::change_insns -- must go from a valid state to a valid
> state. That is, the RTL must be self-consistent before every individual
> call to function_info::change_insns and must be self-consistent after
> every individual call to function_info::change_insns.
>
> This is what I meant before about:
>
> ... if we're removing a definition, all uses in "real"
> debug and non-debug insns must be removed either earlier than the
> definition or at the same time as the definition. No such uses
> should remain.
>
> Since you want to update all uses of register 178, you need to include
> those updates in the same change set as the change to insns 130 and 131,
> rather than doing them later.
The patch isn't using function_info::change_insns though. It's calling
the private remove_use function directly.
>> The patch shouldn't rely on:
>>
>>> diff --git a/gcc/rtl-ssa/functions.h b/gcc/rtl-ssa/functions.h
>>> index 567701c7995..3003251e62c 100644
>>> --- a/gcc/rtl-ssa/functions.h
>>> +++ b/gcc/rtl-ssa/functions.h
>>> @@ -222,6 +222,13 @@ public:
>>> template<typename T, typename... Ts>
>>> T *change_alloc (obstack_watermark &wm, Ts... args);
>>>
>>> + auto_vec<access_info *> &get_m_temp_defs () { return m_temp_defs; }
>>> +
>>> + template<typename T, typename... Ts>
>>> + T *allocate (Ts... args);
>>> +
>>> + void remove_use (use_info *);
>>> +
>>> private:
>>> class bb_phi_info;
>>> class build_info;
>>
>> Those aren't things that rs6000 code should be doing directly.
>>
> Would you mind explaining where to handle this.
Each change to an instruction should be done via function_info::change_insns.
The idea is that change should be structured as follows:
(A) Call crtl->ssa->new_change_attempt ()
(B) For each instruction that you want to change:
(1) Create an insn_change.
(2) In that insn_change, describe the new uses and defs, and the
range of possible instruction positions (if the instruction is
allowed to move).
(3) Use validate_change/insn_propagation/etc. to change the RTL of
the instruction.
[(2) and (3) could be done in the opposite order]
At this stage, nothing is committed. No insn_infos have changed and
all insn patterns can be reset to their original state by cancel_changes
(which happens automatically when an uncommitted change attempt goes out
of scope).
Next:
(C) Check whether the set of changes are valid and self-consistent.
Also check whether they are a win. If no to either, abort the change.
(D) Call function_info::change_insns to commit and finalise the changes.
All the logic for updating "permanent" rtl-ssa structures should go in
function_info::change_insns. It shouldn't be done by pair-fusion itself,
or by target code.
pair-fusion already works like this. I think the rs6000 pass just needs
to hook into (B), so that it can update the uses fed by loads and the
definitions that feed stores.
>>> +
>>> + rtx_insn *rtl_insn = info->rtl ();
>>> + insn_propagation prop (rtl_insn, old_dest, src);
>>> + if (!prop.apply_to_pattern (&PATTERN (rtl_insn)))
>>> + gcc_assert (0);
>>> + }
>>> + }
>>> +}
>>
>> Could you combine this with the code that creates the insn_change
>> for the insn, rather than doing that in a separate function?
>> IMO it's better to keep the creation of insn_changes together
>> with the changes that they describe.
>>
>
> Sorry I didn't get this. Would you mind explaining where to make
> the above change.
The above answer is supposed to cover this too. Each change to a use
insn should involve:
- creating an insn_change
- using insn_propagation to change the rtl
- working out the new uses for the insn, and storing them in the
insn_change (not the insn itself)
- adding the insn_change to the list of changes that pair-fusion performs
for the load fusion.
Then, the loads and their uses will be updated in one go, by one call
to function_info::change_insns.
Please let me know if the explanation doesn't make sense. It's difficult
to spot the unstated assumptions when explaining one's own code. :)
Thanks,
Richard