[2/3] xtensa: Add 'subtraction from constant' insn pattern

Message ID d58e2cda-ad7a-3e54-d46a-f8d907f892e3@yahoo.co.jp
State Committed
Commit 9b867c8281ee313cf6ec737d8f4a9ba7ef78408e
Headers
Series [1/3] xtensa: Addendum of the commit e33d2dcb463161a110ac345a451132ce8b2b23d9 |

Commit Message

Takayuki 'January June' Suwa May 25, 2023, 3:07 p.m. UTC
  This patch makes try to eliminate using temporary pseudo for
'(minus:SI (const_int) (reg:SI))' if the addition of negative constant
value can be emitted in a single machine instruction.

    /* example */
    int test0(int x) {
      return 1 - x;
    }
    int test1(int x) {
      return 100 - x;
    }
    int test2(int x) {
      return 25600 - x;
    }

    ;; before
    test0:
	movi.n	a9, 1
	sub	a2, a9, a2
	ret.n
    test1:
	movi	a9, 0x64
	sub	a2, a9, a2
	ret.n
    test2:
	movi.n	a9, 0x19
	slli	a9, a9, 10
	sub	a2, a9, a2
	ret.n

    ;; after
    test0:
	addi.n	a2, a2, -1
	neg	a2, a2
	ret.n
    test1:
	addi	a2, a2, -100
	neg	a2, a2
	ret.n
    test2:
	addmi	a2, a2, -0x6400
	neg	a2, a2
	ret.n

    gcc/ChangeLog:

	* config/xtensa/xtensa-protos.h (xtensa_m1_or_1_thru_15):
	New prototype.
	* config/xtensa/xtensa.cc (xtensa_m1_or_1_thru_15):
	New function.
	* config/xtensa/constraints.md (O):
	Change to use the above function.
	* config/xtensa/xtensa.md (*subsi3_from_const):
	New insn_and_split pattern.
---
 gcc/config/xtensa/constraints.md  |  2 +-
 gcc/config/xtensa/xtensa-protos.h |  1 +
 gcc/config/xtensa/xtensa.cc       |  7 +++++++
 gcc/config/xtensa/xtensa.md       | 24 ++++++++++++++++++++++++
 4 files changed, 33 insertions(+), 1 deletion(-)
  

Comments

Max Filippov May 26, 2023, 10:20 a.m. UTC | #1
On Thu, May 25, 2023 at 8:13 AM Takayuki 'January June' Suwa
<jjsuwa_sys3175@yahoo.co.jp> wrote:
>
> This patch makes try to eliminate using temporary pseudo for
> '(minus:SI (const_int) (reg:SI))' if the addition of negative constant
> value can be emitted in a single machine instruction.
>
>     /* example */
>     int test0(int x) {
>       return 1 - x;
>     }
>     int test1(int x) {
>       return 100 - x;
>     }
>     int test2(int x) {
>       return 25600 - x;
>     }
>
>     ;; before
>     test0:
>         movi.n  a9, 1
>         sub     a2, a9, a2
>         ret.n
>     test1:
>         movi    a9, 0x64
>         sub     a2, a9, a2
>         ret.n
>     test2:
>         movi.n  a9, 0x19
>         slli    a9, a9, 10
>         sub     a2, a9, a2
>         ret.n
>
>     ;; after
>     test0:
>         addi.n  a2, a2, -1
>         neg     a2, a2
>         ret.n
>     test1:
>         addi    a2, a2, -100
>         neg     a2, a2
>         ret.n
>     test2:
>         addmi   a2, a2, -0x6400
>         neg     a2, a2
>         ret.n
>
>     gcc/ChangeLog:
>
>         * config/xtensa/xtensa-protos.h (xtensa_m1_or_1_thru_15):
>         New prototype.
>         * config/xtensa/xtensa.cc (xtensa_m1_or_1_thru_15):
>         New function.
>         * config/xtensa/constraints.md (O):
>         Change to use the above function.
>         * config/xtensa/xtensa.md (*subsi3_from_const):
>         New insn_and_split pattern.
> ---
>  gcc/config/xtensa/constraints.md  |  2 +-
>  gcc/config/xtensa/xtensa-protos.h |  1 +
>  gcc/config/xtensa/xtensa.cc       |  7 +++++++
>  gcc/config/xtensa/xtensa.md       | 24 ++++++++++++++++++++++++
>  4 files changed, 33 insertions(+), 1 deletion(-)

Regtested for target=xtensa-linux-uclibc, no new regressions.
Committed to master.
  

Patch

diff --git a/gcc/config/xtensa/constraints.md b/gcc/config/xtensa/constraints.md
index 53e4d0d8dd1..5cade1db8ff 100644
--- a/gcc/config/xtensa/constraints.md
+++ b/gcc/config/xtensa/constraints.md
@@ -108,7 +108,7 @@ 
 (define_constraint "O"
  "An integer constant that can be used in ADDI.N instructions."
  (and (match_code "const_int")
-      (match_test "ival == -1 || IN_RANGE (ival, 1, 15)")))
+      (match_test "xtensa_m1_or_1_thru_15 (ival)")))
 
 (define_constraint "P"
  "An integer constant that can be used as a mask value in an EXTUI
diff --git a/gcc/config/xtensa/xtensa-protos.h b/gcc/config/xtensa/xtensa-protos.h
index 64cbf27c248..ec715b44e4d 100644
--- a/gcc/config/xtensa/xtensa-protos.h
+++ b/gcc/config/xtensa/xtensa-protos.h
@@ -27,6 +27,7 @@  extern bool xtensa_simm8x256 (HOST_WIDE_INT);
 extern bool xtensa_simm12b (HOST_WIDE_INT);
 extern bool xtensa_b4const_or_zero (HOST_WIDE_INT);
 extern bool xtensa_b4constu (HOST_WIDE_INT);
+extern bool xtensa_m1_or_1_thru_15 (HOST_WIDE_INT);
 extern bool xtensa_mask_immediate (HOST_WIDE_INT);
 extern bool xtensa_mem_offset (unsigned, machine_mode);
 
diff --git a/gcc/config/xtensa/xtensa.cc b/gcc/config/xtensa/xtensa.cc
index e3af78cd228..46ab9f36b56 100644
--- a/gcc/config/xtensa/xtensa.cc
+++ b/gcc/config/xtensa/xtensa.cc
@@ -471,6 +471,13 @@  xtensa_b4constu (HOST_WIDE_INT v)
 }
 
 
+bool
+xtensa_m1_or_1_thru_15 (HOST_WIDE_INT v)
+{
+  return v == -1 || IN_RANGE (v, 1, 15);
+}
+
+
 bool
 xtensa_mask_immediate (HOST_WIDE_INT v)
 {
diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md
index 11258125165..113b313026e 100644
--- a/gcc/config/xtensa/xtensa.md
+++ b/gcc/config/xtensa/xtensa.md
@@ -216,6 +216,30 @@ 
    (set_attr "mode"	"SI")
    (set_attr "length"	"3")])
 
+(define_insn_and_split "*subsi3_from_const"
+  [(set (match_operand:SI 0 "register_operand" "=a")
+	(minus:SI (match_operand:SI 1 "const_int_operand" "i")
+		  (match_operand:SI 2 "register_operand" "r")))]
+  "xtensa_simm8 (-INTVAL (operands[1]))
+   || xtensa_simm8x256 (-INTVAL (operands[1]))"
+  "#"
+  "&& 1"
+  [(set (match_dup 0)
+	(plus:SI (match_dup 2)
+		 (match_dup 1)))
+   (set (match_dup 0)
+	(neg:SI (match_dup 0)))]
+{
+  operands[1] = GEN_INT (-INTVAL (operands[1]));
+}
+  [(set_attr "type"	"arith")
+   (set_attr "mode"	"SI")
+   (set (attr "length")
+	(if_then_else (match_test "TARGET_DENSITY
+				   && xtensa_m1_or_1_thru_15 (-INTVAL (operands[1]))")
+		      (const_int 5)
+		      (const_int 6)))])
+
 (define_insn "subsf3"
   [(set (match_operand:SF 0 "register_operand" "=f")
 	(minus:SF (match_operand:SF 1 "register_operand" "f")