https://gcc.gnu.org/g:093584abb854559393e36cd4cdcf9dc4862dd046

commit r15-5731-g093584abb854559393e36cd4cdcf9dc4862dd046
Author: Uros Bizjak <ubiz...@gmail.com>
Date:   Wed Nov 27 20:45:25 2024 +0100

    i386: x86 can use x >> y for x >> 32+y [PR36503]
    
    x86 targets mask 32-bit shifts with a 5-bit mask (and 64-bit with 6-bit 
mask),
    so they can use x >> y instead of x >> 32+y.
    
    The optimization converts:
    
            leal    32(%rsi), %ecx
            sall    %cl, %eax
    
    to:
            sall    %cl, %eax
    
            PR target/36503
    
    gcc/ChangeLog:
    
            * config/i386/i386.md (*ashl<mode>3_add):
            New define_insn_and_split pattern.
            (*ashl<mode>3_add_1): Ditto.
            (*<insn><mode>3_add): Ditto.
            (*<insn><mode>3_add_1): Ditto.
            (*ashl<mode>3_sub): Rename from *ashl<mode>3_negcnt.
            (*ashl<mode>3_sub_1): Rename from *ashl<mode>3_negcnt_1.
            (*<insn><mode>3_sub): Rename from *<insn><mode>3_negcnt.
            (*<insn><mode>3_sub_1): Rename from *<insn><mode>3_negcnt_1.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.target/i386/pr36503-3.c: New test.
            * gcc.target/i386/pr36503-4.c: New test.

Diff:
---
 gcc/config/i386/i386.md                   | 100 ++++++++++++++++++++++++++++--
 gcc/testsuite/gcc.target/i386/pr36503-3.c |  20 ++++++
 gcc/testsuite/gcc.target/i386/pr36503-4.c |  19 ++++++
 3 files changed, 135 insertions(+), 4 deletions(-)

diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index df78e4df9d82..2fc48006bca7 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -15896,7 +15896,53 @@
   ""
   [(set_attr "isa" "*,bmi2")])
 
-(define_insn_and_split "*ashl<mode>3_negcnt"
+(define_insn_and_split "*ashl<mode>3_add"
+  [(set (match_operand:SWI48 0 "nonimmediate_operand")
+       (ashift:SWI48
+         (match_operand:SWI48 1 "nonimmediate_operand")
+         (subreg:QI
+           (plus
+             (match_operand 2 "int248_register_operand" "c,r")
+             (match_operand 3 "const_int_operand")) 0)))
+   (clobber (reg:CC FLAGS_REG))]
+  "ix86_binary_operator_ok (ASHIFT, <MODE>mode, operands)
+   && (INTVAL (operands[3]) & (<MODE_SIZE> * BITS_PER_UNIT - 1)) == 0
+   && ix86_pre_reload_split ()"
+  "#"
+  "&& 1"
+  [(parallel
+     [(set (match_dup 0)
+          (ashift:SWI48 (match_dup 1)
+                        (match_dup 2)))
+      (clobber (reg:CC FLAGS_REG))])]
+{
+  operands[2] = force_reg (GET_MODE (operands[2]), operands[2]);
+  operands[2] = gen_lowpart (QImode, operands[2]);
+}
+  [(set_attr "isa" "*,bmi2")])
+
+(define_insn_and_split "*ashl<mode>3_add_1"
+  [(set (match_operand:SWI48 0 "nonimmediate_operand")
+       (ashift:SWI48
+         (match_operand:SWI48 1 "nonimmediate_operand")
+         (plus:QI
+           (match_operand:QI 2 "register_operand" "c,r")
+           (match_operand:QI 3 "const_int_operand"))))
+   (clobber (reg:CC FLAGS_REG))]
+  "ix86_binary_operator_ok (ASHIFT, <MODE>mode, operands)
+   && (INTVAL (operands[3]) & (<MODE_SIZE> * BITS_PER_UNIT - 1)) == 0
+   && ix86_pre_reload_split ()"
+  "#"
+  "&& 1"
+  [(parallel
+     [(set (match_dup 0)
+          (ashift:SWI48 (match_dup 1)
+                        (match_dup 2)))
+      (clobber (reg:CC FLAGS_REG))])]
+  ""
+  [(set_attr "isa" "*,bmi2")])
+
+(define_insn_and_split "*ashl<mode>3_sub"
   [(set (match_operand:SWI48 0 "nonimmediate_operand")
        (ashift:SWI48
          (match_operand:SWI48 1 "nonimmediate_operand")
@@ -15927,7 +15973,7 @@
 }
   [(set_attr "isa" "*,bmi2")])
 
-(define_insn_and_split "*ashl<mode>3_negcnt_1"
+(define_insn_and_split "*ashl<mode>3_sub_1"
   [(set (match_operand:SWI48 0 "nonimmediate_operand")
        (ashift:SWI48
          (match_operand:SWI48 1 "nonimmediate_operand")
@@ -16678,7 +16724,53 @@
   ""
   [(set_attr "isa" "*,bmi2")])
 
-(define_insn_and_split "*<insn><mode>3_negcnt"
+(define_insn_and_split "*<insn><mode>3_add"
+  [(set (match_operand:SWI48 0 "nonimmediate_operand")
+       (any_shiftrt:SWI48
+         (match_operand:SWI48 1 "nonimmediate_operand")
+         (subreg:QI
+           (plus
+             (match_operand 2 "int248_register_operand" "c,r")
+             (match_operand 3 "const_int_operand")) 0)))
+   (clobber (reg:CC FLAGS_REG))]
+  "ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)
+   && (INTVAL (operands[3]) & (<MODE_SIZE> * BITS_PER_UNIT - 1)) == 0
+   && ix86_pre_reload_split ()"
+  "#"
+  "&& 1"
+  [(parallel
+     [(set (match_dup 0)
+          (any_shiftrt:SWI48 (match_dup 1)
+                             (match_dup 2)))
+      (clobber (reg:CC FLAGS_REG))])]
+{
+  operands[2] = force_reg (GET_MODE (operands[2]), operands[2]);
+  operands[2] = gen_lowpart (QImode, operands[2]);
+}
+  [(set_attr "isa" "*,bmi2")])
+
+(define_insn_and_split "*<insn><mode>3_add_1"
+  [(set (match_operand:SWI48 0 "nonimmediate_operand")
+       (any_shiftrt:SWI48
+         (match_operand:SWI48 1 "nonimmediate_operand")
+         (plus:QI
+           (match_operand:QI 2 "register_operand" "c,r")
+           (match_operand:QI 3 "const_int_operand"))))
+   (clobber (reg:CC FLAGS_REG))]
+  "ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)
+   && (INTVAL (operands[3]) & (<MODE_SIZE> * BITS_PER_UNIT - 1)) == 0
+   && ix86_pre_reload_split ()"
+  "#"
+  "&& 1"
+  [(parallel
+     [(set (match_dup 0)
+          (any_shiftrt:SWI48 (match_dup 1)
+                             (match_dup 2)))
+      (clobber (reg:CC FLAGS_REG))])]
+  ""
+  [(set_attr "isa" "*,bmi2")])
+
+(define_insn_and_split "*<insn><mode>3_sub"
   [(set (match_operand:SWI48 0 "nonimmediate_operand")
        (any_shiftrt:SWI48
          (match_operand:SWI48 1 "nonimmediate_operand")
@@ -16709,7 +16801,7 @@
 }
   [(set_attr "isa" "*,bmi2")])
 
-(define_insn_and_split "*<insn><mode>3_negcnt_1"
+(define_insn_and_split "*<insn><mode>3_sub_1"
   [(set (match_operand:SWI48 0 "nonimmediate_operand")
        (any_shiftrt:SWI48
          (match_operand:SWI48 1 "nonimmediate_operand")
diff --git a/gcc/testsuite/gcc.target/i386/pr36503-3.c 
b/gcc/testsuite/gcc.target/i386/pr36503-3.c
new file mode 100644
index 000000000000..6ac4f416c1b0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr36503-3.c
@@ -0,0 +1,20 @@
+/* PR target/36503 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -masm=att" } */
+/* { dg-additional-options "-mregparm=3" { target ia32 } } */
+/* { dg-final { scan-assembler-not "leal\[ \\t\]+32" } } */
+
+int foo (int i, int n)
+{
+  return i << (32 + n);
+}
+
+int bar (int i, int n)
+{
+  return i >> (32 + n);
+}
+
+unsigned int baz (unsigned int i, int n)
+{
+  return i >> (32 + n);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr36503-4.c 
b/gcc/testsuite/gcc.target/i386/pr36503-4.c
new file mode 100644
index 000000000000..1fd81f26f591
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr36503-4.c
@@ -0,0 +1,19 @@
+/* PR target/36503 */
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -masm=att" } */
+/* { dg-final { scan-assembler-not "leal\[ \\t\]+64" } } */
+
+long long foo (long long i, int n)
+{
+  return i << (64 + n);
+}
+
+long long bar (long long i, int n)
+{
+  return i >> (64 + n);
+}
+
+unsigned long long baz (unsigned long long i, int n)
+{
+  return i >> (64 + n);
+}

Reply via email to