public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r13-4977] Improve ix86_expand_int_movcc to allow condition (mask) sharing.
@ 2023-01-03 13:42 Roger Sayle
  0 siblings, 0 replies; only message in thread
From: Roger Sayle @ 2023-01-03 13:42 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:d0558f420b2a5692fd38ac76ffa97ae6c1726ed9

commit r13-4977-gd0558f420b2a5692fd38ac76ffa97ae6c1726ed9
Author: Roger Sayle <roger@nextmovesoftware.com>
Date:   Tue Jan 3 13:40:47 2023 +0000

    Improve ix86_expand_int_movcc to allow condition (mask) sharing.
    
    This patch modifies the way that ix86_expand_int_movcc generates RTL,
    to allow the condition mask to be shared/reused between multiple
    conditional move sequences.  Such redundancy is common when RTL
    if-conversion transforms non-trivial basic blocks.
    
    As a motivating example, consider the new test case:
    
    int a, b, c, d;
    int foo(int x)
    {
        if (x == 0) {
            a = 3;
            b = 1;
            c = 4;
            d = 1;
        } else {
            a = 5;
            b = 9;
            c = 2;
            d = 7;
        }
        return x;
    }
    
    This is currently compiled, with -O2, to:
    
    foo:    cmpl    $1, %edi
            movl    %edi, %eax
            sbbl    %edi, %edi
            andl    $-2, %edi
            addl    $5, %edi
            cmpl    $1, %eax
            sbbl    %esi, %esi
            movl    %edi, a(%rip)
            andl    $-8, %esi
            addl    $9, %esi
            cmpl    $1, %eax
            sbbl    %ecx, %ecx
            movl    %esi, b(%rip)
            andl    $2, %ecx
            addl    $2, %ecx
            cmpl    $1, %eax
            sbbl    %edx, %edx
            movl    %ecx, c(%rip)
            andl    $-6, %edx
            addl    $7, %edx
            movl    %edx, d(%rip)
            ret
    
    Notice that the if-then-else blocks have been if-converted into four
    conditional move sequences/assignments, each consisting of cmpl, sbbl,
    andl and addl.  However, as the conditions are the same, the cmpl and
    sbbl instructions used to generate the mask could be shared by CSE.
    
    This patch enables that so that we now generate:
    
    foo:    cmpl    $1, %edi
            movl    %edi, %eax
            sbbl    %edx, %edx
            movl    %edx, %edi
            movl    %edx, %esi
            movl    %edx, %ecx
            andl    $-6, %edx
            andl    $-2, %edi
            andl    $-8, %esi
            andl    $2, %ecx
            addl    $7, %edx
            addl    $5, %edi
            addl    $9, %esi
            addl    $2, %ecx
            movl    %edx, d(%rip)
            movl    %edi, a(%rip)
            movl    %esi, b(%rip)
            movl    %ecx, c(%rip)
            ret
    
    Notice, the code now contains only a single cmpl and a single sbbl,
    with result being shared (via movl).
    
    2023-01-03  Roger Sayle  <roger@nextmovesoftware.com>
    
    gcc/ChangeLog
            * config/i386/i386-expand.cc (ix86_expand_int_movcc): Rewrite
            RTL expansion to allow condition (mask) to be shared/reused,
            by avoiding overwriting pseudos and adding REG_EQUAL notes.
    
    gcc/testsuite/ChangeLog
            * gcc.target/i386/cmov10.c: New test case.

Diff:
---
 gcc/config/i386/i386-expand.cc         | 46 +++++++++++++++-------------------
 gcc/testsuite/gcc.target/i386/cmov10.c | 21 ++++++++++++++++
 2 files changed, 41 insertions(+), 26 deletions(-)

diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc
index 3eddbc94360..4fd7c3ccd91 100644
--- a/gcc/config/i386/i386-expand.cc
+++ b/gcc/config/i386/i386-expand.cc
@@ -3284,8 +3284,8 @@ ix86_expand_int_movcc (rtx operands[])
 	  || negate_cc_compare_p
 	  || ix86_expand_carry_flag_compare (code, op0, op1, &compare_op))
 	{
-	  /* Detect overlap between destination and compare sources.  */
-	  rtx tmp = out;
+	  /* Place comparison result in its own pseudo.  */
+	  rtx tmp = gen_reg_rtx (mode);
 
 	  if (negate_cc_compare_p)
 	    {
@@ -3295,7 +3295,6 @@ ix86_expand_int_movcc (rtx operands[])
 		emit_insn (gen_x86_negsi_ccc (gen_reg_rtx (SImode),
 					      gen_lowpart (SImode, op0)));
 
-	      tmp = gen_reg_rtx (mode);
 	      if (mode == DImode)
 		emit_insn (gen_x86_movdicc_0_m1_neg (tmp));
 	      else
@@ -3337,9 +3336,6 @@ ix86_expand_int_movcc (rtx operands[])
 		}
 	      diff = ct - cf;
 
-	      if (reg_overlap_mentioned_p (out, compare_op))
-		tmp = gen_reg_rtx (mode);
-
 	      if (mode == DImode)
 		emit_insn (gen_x86_movdicc_0_m1 (tmp, flags, compare_op));
 	      else
@@ -3358,6 +3354,11 @@ ix86_expand_int_movcc (rtx operands[])
 	      tmp = emit_store_flag (tmp, code, op0, op1, VOIDmode, 0, -1);
 	    }
 
+	  /* Add a REG_EQUAL note to allow condition to be shared.  */
+	  rtx note = gen_rtx_fmt_ee (code, mode, op0, op1);
+	  set_unique_reg_note (get_last_insn (), REG_EQUAL,
+			       gen_rtx_NEG (mode, note));
+
 	  if (diff == 1)
 	    {
 	      /*
@@ -3368,9 +3369,8 @@ ix86_expand_int_movcc (rtx operands[])
 	       * Size 5 - 8.
 	       */
 	      if (ct)
-		tmp = expand_simple_binop (mode, PLUS,
-					   tmp, GEN_INT (ct),
-					   copy_rtx (tmp), 1, OPTAB_DIRECT);
+		tmp = expand_simple_binop (mode, PLUS, tmp, GEN_INT (ct),
+					   NULL_RTX, 1, OPTAB_DIRECT);
 	    }
 	  else if (cf == -1)
 	    {
@@ -3381,9 +3381,8 @@ ix86_expand_int_movcc (rtx operands[])
 	       *
 	       * Size 8.
 	       */
-	      tmp = expand_simple_binop (mode, IOR,
-					 tmp, GEN_INT (ct),
-					 copy_rtx (tmp), 1, OPTAB_DIRECT);
+	      tmp = expand_simple_binop (mode, IOR, tmp, GEN_INT (ct),
+					 NULL_RTX, 1, OPTAB_DIRECT);
 	    }
 	  else if (diff == -1 && ct)
 	    {
@@ -3395,11 +3394,10 @@ ix86_expand_int_movcc (rtx operands[])
 	       *
 	       * Size 8 - 11.
 	       */
-	      tmp = expand_simple_unop (mode, NOT, tmp, copy_rtx (tmp), 1);
+	      tmp = expand_simple_unop (mode, NOT, tmp, NULL_RTX, 1);
 	      if (cf)
-		tmp = expand_simple_binop (mode, PLUS,
-					   copy_rtx (tmp), GEN_INT (cf),
-					   copy_rtx (tmp), 1, OPTAB_DIRECT);
+		tmp = expand_simple_binop (mode, PLUS, tmp, GEN_INT (cf),
+					   NULL_RTX, 1, OPTAB_DIRECT);
 	    }
 	  else
 	    {
@@ -3417,22 +3415,18 @@ ix86_expand_int_movcc (rtx operands[])
 		{
 		  cf = ct;
 		  ct = 0;
-		  tmp = expand_simple_unop (mode, NOT, tmp, copy_rtx (tmp), 1);
+		  tmp = expand_simple_unop (mode, NOT, tmp, NULL_RTX, 1);
 		}
 
-	      tmp = expand_simple_binop (mode, AND,
-					 copy_rtx (tmp),
+	      tmp = expand_simple_binop (mode, AND, tmp,
 					 gen_int_mode (cf - ct, mode),
-					 copy_rtx (tmp), 1, OPTAB_DIRECT);
+					 NULL_RTX, 1, OPTAB_DIRECT);
 	      if (ct)
-		tmp = expand_simple_binop (mode, PLUS,
-					   copy_rtx (tmp), GEN_INT (ct),
-					   copy_rtx (tmp), 1, OPTAB_DIRECT);
+		tmp = expand_simple_binop (mode, PLUS, tmp, GEN_INT (ct),
+					   NULL_RTX, 1, OPTAB_DIRECT);
 	    }
 
-	  if (!rtx_equal_p (tmp, out))
-	    emit_move_insn (copy_rtx (out), copy_rtx (tmp));
-
+	  emit_move_insn (out, tmp);
 	  return true;
 	}
 
diff --git a/gcc/testsuite/gcc.target/i386/cmov10.c b/gcc/testsuite/gcc.target/i386/cmov10.c
new file mode 100644
index 00000000000..142b4d7d051
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/cmov10.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+int a, b, c, d;
+
+int foo(int x)
+{
+    if (x == 0) {
+        a = 3;
+        b = 1;
+        c = 4;
+        d = 1;
+    } else {
+        a = 5;
+        b = 9;
+        c = 2;
+        d = 7;
+    }
+    return x;
+}
+/* { dg-final { scan-assembler-times "cmpl" 1 } } */
+/* { dg-final { scan-assembler-times "sbbl" 1 } } */

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-01-03 13:42 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-01-03 13:42 [gcc r13-4977] Improve ix86_expand_int_movcc to allow condition (mask) sharing Roger Sayle

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).