> Am 18.09.2018 um 02:57 schrieb Jeff Law <l...@redhat.com>:
> 
> On 9/5/18 2:34 AM, Ilya Leoshkevich wrote:
>> --- a/gcc/cfgcleanup.c
>> +++ b/gcc/cfgcleanup.c
>> @@ -2624,7 +2624,7 @@ bb_is_just_return (basic_block bb, rtx_insn **ret, 
>> rtx_insn **use)
>>       {
>>      rtx pat = PATTERN (insn);
>> 
>> -    if (!*ret && ANY_RETURN_P (pat))
>> +    if (!*ret && (ANY_RETURN_P (pat) || return_in_parallel (pat)))
>>        *ret = insn;
>>      else if (!*ret && !*use && GET_CODE (pat) == USE
>>          && REG_P (XEXP (pat, 0))
> So what else is in the return insn that requires you to test for
> return_in_parallel?  If we're going to allow a return in a parallel,
> here I think we need to tighten down its form given the intended ways
> bb_is_just_return is supposed to be used.  Essentially other side
> effects would seem to be forbidden in the parallel.  ie, you could have
> a PARALLEL with a return and use inside, but not a return with anything
> else inside (such as a clobber).

Yes, it’s RETURN+USE.  I allowed CLOBBERs, because bb_is_just_return
already allows them, but I don’t think it's necessary for the S/390 use
case, so I can make it more restrictive if needed.

> 
> Why do you need to make a copy of the parallel RTX in redirect_exp_1?
> We don't do it for other cases -- why can't we just use validate_change
> like all the other RTXs?
> 
> 
>> /* Throughout LOC, redirect OLABEL to NLABEL.  Treat null OLABEL or
>>    NLABEL as a return.  Accrue modifications into the change group.  */
>> 
>> @@ -1437,9 +1457,22 @@ redirect_exp_1 (rtx *loc, rtx olabel, rtx nlabel, 
>> rtx_insn *insn)
>>   if ((code == LABEL_REF && label_ref_label (x) == olabel)
>>       || x == olabel)
>>     {
>> -      x = redirect_target (nlabel);
>> -      if (GET_CODE (x) == LABEL_REF && loc == &PATTERN (insn))
>> -    x = gen_rtx_SET (pc_rtx, x);
>> +      rtx *nret = return_in_parallel (nlabel);
>> +
>> +      if (nret)
>> +    {
>> +      rtx npat;
>> +
>> +      x = *nret;
>> +      npat = copy_update_parallel (nlabel, nret, PATTERN (insn));
>> +      validate_change (insn, &PATTERN (insn), npat, 1);
>> +    }
>> +      else
>> +    {
>> +      x = redirect_target (nlabel);
>> +      if (GET_CODE (x) == LABEL_REF && loc == &PATTERN (insn))
>> +        x = gen_rtx_SET (pc_rtx, x);
>> +    }
>>       validate_change (insn, loc, x, 1);
> Why the need to use copy_update_parallel here?  Is there a reason why
> validate_change is insufficient?

The original RTL has the following form:

(jump_insn 1 (set %pc (if_then_else (ne %cc 0) (label_ref 2) %pc)))
...
(code_label 2)
(jump_insn 3 (parallel [(return) (use %r14)]))

and the goal is to transform (jump_insn 1) to:

(jump_insn 1
 (parallel
  [(set %pc (if_then_else (ne %cc 0) (return) %pc))
   (use %r14)]))

while keeping (code_label 2) and (jump_insn 3) intact.  So I have to
create a new PARALLEL based on the original one.

> 
> 
>>       return;
>>     }
>> @@ -1551,10 +1584,15 @@ void
>> redirect_jump_2 (rtx_jump_insn *jump, rtx olabel, rtx nlabel, int 
>> delete_unused,
>>               int invert)
>> {
>> +  rtx *ret;
>>   rtx note;
>> 
>>   gcc_assert (JUMP_LABEL (jump) == olabel);
>> 
>> +  ret = return_in_parallel (nlabel);
>> +  if (ret)
>> +    nlabel = *ret;
> Why does return_in_parallel return an rtx *?  Can't you just return the
> rtx and avoid the unnecessary dereferencing?  I guess this ultimately
> comes back to why can't you use validate_change like everyone else in
> redirect_exp_1?

Right, this is related.  This is to indicate to copy_update_parallel,
which of the side-effects need to be updated.

Reply via email to