i386: Eliminate sign extension after logic operation [PR89954]

Message ID CAFULd4a1UK7Oji8xubh5WgYEvaTMU9ATjCFzpD0TZXH5KcSQ4Q@mail.gmail.com
State Committed
Commit 6f4459c478b1c09e4b5e7d629fbf46d2a4fe4560
Headers
Series i386: Eliminate sign extension after logic operation [PR89954] |

Commit Message

Uros Bizjak Sept. 30, 2021, 5:37 p.m. UTC
  Convert (sign_extend:WIDE (any_logic:NARROW (memory, immediate)))
to (any_logic:WIDE (sign_extend (memory)), (sign_extend (immediate))).
This eliminates sign extension after logic operation.

2021-09-30  Uroš Bizjak  <ubizjak@gmail.com>

gcc/
    PR target/89954
    * config/i386/i386.md
    (sign_extend:WIDE (any_logic:NARROW (memory, immediate)) splitters):
    New splitters.

gcc/testsuite/
    PR target/89954
    * gcc.target/i386/pr89954.c: New test.

Bootstrapped and regression tested on x86_64-linux-gnu {,-m32}.

Pushed to master.

Uros.
  

Patch

diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 758d7d1e3c0..04cb3bf6a33 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -10210,6 +10210,40 @@ 
   [(set_attr "type" "alu")
    (set_attr "mode" "<MODE>")])
 
+;; convert (sign_extend:WIDE (any_logic:NARROW (memory, immediate)))
+;; to (any_logic:WIDE (sign_extend (memory)), (sign_extend (immediate))).
+;; This eliminates sign extension after logic operation.
+
+(define_split
+  [(set (match_operand:SWI248 0 "register_operand")
+	(sign_extend:SWI248
+	  (any_logic:QI (match_operand:QI 1 "memory_operand")
+			(match_operand:QI 2 "const_int_operand"))))]
+  ""
+  [(set (match_dup 3) (sign_extend:SWI248 (match_dup 1)))
+   (set (match_dup 0) (any_logic:SWI248 (match_dup 3) (match_dup 2)))]
+  "operands[3] = gen_reg_rtx (<MODE>mode);")
+
+(define_split
+  [(set (match_operand:SWI48 0 "register_operand")
+	(sign_extend:SWI48
+	  (any_logic:HI (match_operand:HI 1 "memory_operand")
+			(match_operand:HI 2 "const_int_operand"))))]
+  ""
+  [(set (match_dup 3) (sign_extend:SWI48 (match_dup 1)))
+   (set (match_dup 0) (any_logic:SWI48 (match_dup 3) (match_dup 2)))]
+  "operands[3] = gen_reg_rtx (<MODE>mode);")
+
+(define_split
+  [(set (match_operand:DI 0 "register_operand")
+	(sign_extend:DI
+	  (any_logic:SI (match_operand:SI 1 "memory_operand")
+			(match_operand:SI 2 "const_int_operand"))))]
+  "TARGET_64BIT"
+  [(set (match_dup 3) (sign_extend:DI (match_dup 1)))
+   (set (match_dup 0) (any_logic:DI (match_dup 3) (match_dup 2)))]
+  "operands[3] = gen_reg_rtx (DImode);")
+
 (define_insn "*<code><mode>_2"
   [(set (reg FLAGS_REG)
 	(compare (any_or:SWI
diff --git a/gcc/testsuite/gcc.target/i386/pr89954.c b/gcc/testsuite/gcc.target/i386/pr89954.c
new file mode 100644
index 00000000000..c1e9f3a9562
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr89954.c
@@ -0,0 +1,45 @@ 
+/* PR target/89954 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+signed char ab;
+
+short aw;
+
+int al;
+
+short sext_andbw (void) { return ab & -2; }
+short sext_orbw (void) { return ab | -3; }
+short sext_xorbw (void) { return ab ^ -4; }
+
+int sext_andbl (void) { return ab & -2; }
+int sext_orbl (void) { return ab | -3; }
+int sext_xorbl (void) { return ab ^ -4; }
+
+int sext_andwl (void) { return aw & -2; }
+int sext_orwl (void) { return aw | -3; }
+int sext_xorwl (void) { return aw ^ -4; }
+
+#ifdef __x86_64__
+
+long long sext_andbq (void) { return ab & -2; }
+long long sext_orbq (void) { return ab | -3; }
+long long sext_xorbq (void) { return ab ^ -4; }
+
+long long sext_andwq (void) { return aw & -2; }
+long long sext_orwq (void) { return aw | -3; }
+long long sext_xorwq (void) { return aw ^ -4; }
+
+long long sext_andlq (void) { return al & -2; }
+long long sext_orlq (void) { return al | -3; }
+long long sext_xorlq (void) { return al ^ -4; }
+
+#endif
+
+/* { dg-final { scan-assembler-times "movsbw" 3 } } */
+/* { dg-final { scan-assembler-times "movsbl" 3 } } */
+/* { dg-final { scan-assembler-times "movswl" 3 } } */
+
+/* { dg-final { scan-assembler-times "movsbq" 3 { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-times "movswq" 3 { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-times "movslq" 3 { target { ! ia32 } } } } */