public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Richard Biener <rguenther@suse.de>
To: Jakub Jelinek <jakub@redhat.com>
Cc: gcc-patches@gcc.gnu.org, Andrew Pinski <pinskia@gmail.com>
Subject: Re: [PATCH] phiopt: Improve value_replacement [PR104645]
Date: Fri, 1 Apr 2022 11:46:54 +0200 (CEST)	[thread overview]
Message-ID: <2np38no2-58qs-4s6q-1o4o-8p165q1o85@fhfr.qr> (raw)
In-Reply-To: <YkbFWnnF+DFX+Qy1@tucnak>

On Fri, 1 Apr 2022, Jakub Jelinek wrote:

> Hi!
> 
> The following patch fixes the P1 regression by reusing existing
> value_replacement code.  That function already has code to
> handle simple preparation statements (casts, and +,&,|,^ binary
> assignments) before a final binary assignment (which can be
> much wider range of ops).  When we have e.g.
>       if (y_3(D) == 0)
>         goto <bb 4>;
>       else
>         goto <bb 3>;
>      <bb 3>:
>       y_4 = y_3(D) & 31;
>       _1 = (int) y_4;
>       _6 = x_5(D) r<< _1;
>      <bb 4>:
>       # _2 = PHI <x_5(D)(2), _6(3)>
> the preparation statements y_4 = y_3(D) & 31; and
> _1 = (int) y_4; are handled by constant evaluation, passing through
> y_3(D) = 0 initially and propagating that through the assignments
> with checking that UB isn't invoked.  But the final
> _6 = x_5(D) r<< _1; assign is handled differently, either through
> neutral_element_p or absorbing_element_p.
> In the first function below we now have:
>   <bb 2> [local count: 1073741824]:
>   if (i_2(D) != 0)
>     goto <bb 3>; [50.00%]
>   else
>     goto <bb 4>; [50.00%]
> 
>   <bb 3> [local count: 536870913]:
>   _3 = i_2(D) & 1;
>   iftmp.0_4 = (int) _3;
> 
>   <bb 4> [local count: 1073741824]:
>   # iftmp.0_1 = PHI <iftmp.0_4(3), 0(2)>
> where in GCC 11 we had:
>   <bb 2> :
>   if (i_3(D) != 0)
>     goto <bb 3>; [INV]
>   else
>     goto <bb 4>; [INV]
> 
>   <bb 3> :
>   i.1_1 = (int) i_3(D);
>   iftmp.0_5 = i.1_1 & 1;
> 
>   <bb 4> :
>   # iftmp.0_2 = PHI <iftmp.0_5(3), 0(2)>
> Current value_replacement can handle the latter as the last
> stmt of middle_bb is a binary op that in this case satisfies
> absorbing_element_p.
> But the former we can't handle, as the last stmt in middle_bb
> is a cast.
> 
> The patch makes it work in that case by pretending all of middle_bb
> are the preparation statements and there is no binary assign at the
> end, so everything is handled through the constant evaluation.
> We simply set at the start of middle_bb the lhs of comparison
> virtually to the rhs, propagate it through and at the end
> see if virtually the arg0 of the PHI is equal to arg1 of it.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

OK.

> For GCC 13, I think we just should throw away all the neutral/absorbing
> element stuff and do the constant evaluation of the whole middle_bb
> and handle that way all the ops we currently handle in neutral/absorbing
> element.

Agreed - that would be a nice cleanup.

Thanks,
Richard.

> 2022-04-01  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR tree-optimization/104645
> 	* tree-ssa-phiopt.cc (value_replacement): If assign has
> 	CONVERT_EXPR_CODE_P rhs_code, treat it like a preparation
> 	statement with constant evaluation.
> 
> 	* gcc.dg/tree-ssa/pr104645.c: New test.
> 
> --- gcc/tree-ssa-phiopt.cc.jj	2022-01-18 11:59:00.089974814 +0100
> +++ gcc/tree-ssa-phiopt.cc	2022-03-31 14:38:27.537149245 +0200
> @@ -1395,11 +1395,22 @@ value_replacement (basic_block cond_bb,
>  
>    gimple *assign = gsi_stmt (gsi);
>    if (!is_gimple_assign (assign)
> -      || gimple_assign_rhs_class (assign) != GIMPLE_BINARY_RHS
>        || (!INTEGRAL_TYPE_P (TREE_TYPE (arg0))
>  	  && !POINTER_TYPE_P (TREE_TYPE (arg0))))
>      return 0;
>  
> +  if (gimple_assign_rhs_class (assign) != GIMPLE_BINARY_RHS)
> +    {
> +      /* If last stmt of the middle_bb is a conversion, handle it like
> +	 a preparation statement through constant evaluation with
> +	 checking for UB.  */
> +      enum tree_code sc = gimple_assign_rhs_code (assign);
> +      if (CONVERT_EXPR_CODE_P (sc))
> +	assign = NULL;
> +      else
> +	return 0;
> +    }
> +
>    /* Punt if there are (degenerate) PHIs in middle_bb, there should not be.  */
>    if (!gimple_seq_empty_p (phi_nodes (middle_bb)))
>      return 0;
> @@ -1430,7 +1441,8 @@ value_replacement (basic_block cond_bb,
>    int prep_cnt;
>    for (prep_cnt = 0; ; prep_cnt++)
>      {
> -      gsi_prev_nondebug (&gsi);
> +      if (prep_cnt || assign)
> +	gsi_prev_nondebug (&gsi);
>        if (gsi_end_p (gsi))
>  	break;
>  
> @@ -1450,7 +1462,8 @@ value_replacement (basic_block cond_bb,
>  	  || !INTEGRAL_TYPE_P (TREE_TYPE (lhs))
>  	  || !INTEGRAL_TYPE_P (TREE_TYPE (rhs1))
>  	  || !single_imm_use (lhs, &use_p, &use_stmt)
> -	  || use_stmt != (prep_cnt ? prep_stmt[prep_cnt - 1] : assign))
> +	  || ((prep_cnt || assign)
> +	      && use_stmt != (prep_cnt ? prep_stmt[prep_cnt - 1] : assign)))
>  	return 0;
>        switch (gimple_assign_rhs_code (g))
>  	{
> @@ -1483,10 +1496,6 @@ value_replacement (basic_block cond_bb,
>  	 >= 3 * estimate_num_insns (cond, &eni_time_weights))
>      return 0;
>  
> -  tree lhs = gimple_assign_lhs (assign);
> -  tree rhs1 = gimple_assign_rhs1 (assign);
> -  tree rhs2 = gimple_assign_rhs2 (assign);
> -  enum tree_code code_def = gimple_assign_rhs_code (assign);
>    tree cond_lhs = gimple_cond_lhs (cond);
>    tree cond_rhs = gimple_cond_rhs (cond);
>  
> @@ -1516,16 +1525,39 @@ value_replacement (basic_block cond_bb,
>  	return 0;
>      }
>  
> +  tree lhs, rhs1, rhs2;
> +  enum tree_code code_def;
> +  if (assign)
> +    {
> +      lhs = gimple_assign_lhs (assign);
> +      rhs1 = gimple_assign_rhs1 (assign);
> +      rhs2 = gimple_assign_rhs2 (assign);
> +      code_def = gimple_assign_rhs_code (assign);
> +    }
> +  else
> +    {
> +      gcc_assert (prep_cnt > 0);
> +      lhs = cond_lhs;
> +      rhs1 = NULL_TREE;
> +      rhs2 = NULL_TREE;
> +      code_def = ERROR_MARK;
> +    }
> +
>    if (((code == NE_EXPR && e1 == false_edge)
>  	|| (code == EQ_EXPR && e1 == true_edge))
>        && arg0 == lhs
> -      && ((arg1 == rhs1
> -	   && operand_equal_for_phi_arg_p (rhs2, cond_lhs)
> -	   && neutral_element_p (code_def, cond_rhs, true))
> -	  || (arg1 == rhs2
> +      && ((assign == NULL
> +	   && operand_equal_for_phi_arg_p (arg1, cond_rhs))
> +	  || (assign
> +	      && arg1 == rhs1
> +	      && operand_equal_for_phi_arg_p (rhs2, cond_lhs)
> +	      && neutral_element_p (code_def, cond_rhs, true))
> +	  || (assign
> +	      && arg1 == rhs2
>  	      && operand_equal_for_phi_arg_p (rhs1, cond_lhs)
>  	      && neutral_element_p (code_def, cond_rhs, false))
> -	  || (operand_equal_for_phi_arg_p (arg1, cond_rhs)
> +	  || (assign
> +	      && operand_equal_for_phi_arg_p (arg1, cond_rhs)
>  	      && ((operand_equal_for_phi_arg_p (rhs2, cond_lhs)
>  		   && absorbing_element_p (code_def, cond_rhs, true, rhs2))
>  		  || (operand_equal_for_phi_arg_p (rhs1, cond_lhs)
> @@ -1555,8 +1587,11 @@ value_replacement (basic_block cond_bb,
>  	  gsi_from = gsi_for_stmt (prep_stmt[i]);
>  	  gsi_move_before (&gsi_from, &gsi);
>  	}
> -      gsi_from = gsi_for_stmt (assign);
> -      gsi_move_before (&gsi_from, &gsi);
> +      if (assign)
> +	{
> +	  gsi_from = gsi_for_stmt (assign);
> +	  gsi_move_before (&gsi_from, &gsi);
> +	}
>        replace_phi_edge_with_variable (cond_bb, e1, phi, lhs);
>        return 2;
>      }
> --- gcc/testsuite/gcc.dg/tree-ssa/pr104645.c.jj	2022-03-31 15:02:15.116389726 +0200
> +++ gcc/testsuite/gcc.dg/tree-ssa/pr104645.c	2022-03-31 15:01:45.674817966 +0200
> @@ -0,0 +1,28 @@
> +/* PR tree-optimization/104645 */
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fdump-tree-optimized" } */
> +/* { dg-final { scan-tree-dump-not " = PHI <" "optimized" } } */
> +
> +int
> +foo (unsigned i)
> +{
> +  return i ? i % 2 : 0;
> +}
> +
> +int
> +bar (unsigned i)
> +{
> +  int b = 0;
> +  if (i)
> +    {
> +      unsigned a = i & 1;
> +      b = a;
> +    }
> +  return b;
> +}
> +
> +int
> +baz (unsigned i)
> +{
> +  return i ? i + 4 : 4;
> +}
> 
> 	Jakub
> 
> 

-- 
Richard Biener <rguenther@suse.de>
SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg,
Germany; GF: Ivo Totev; HRB 36809 (AG Nuernberg)

      reply	other threads:[~2022-04-01  9:46 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-04-01  9:26 Jakub Jelinek
2022-04-01  9:46 ` Richard Biener [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=2np38no2-58qs-4s6q-1o4o-8p165q1o85@fhfr.qr \
    --to=rguenther@suse.de \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=jakub@redhat.com \
    --cc=pinskia@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).