From 7da97411b048cdd4e7941b311514f46ea53fe3a2 Mon Sep 17 00:00:00 2001 From: Jeff Law Date: Tue, 1 Dec 2020 21:48:10 -0700 Subject: [PATCH] Use add/sub/neg insns to eliminate compare/test insns on H8 gcc/ * config/h8300/addsub.md (addqi3_clobber_flags): Rename to addqi3_flags and annotate with a for define_subst. (addhi3_h8sx_clobber_flags): Likewise. (subqi3_clobber_flags, sub3_clobber_flags): Likewise. (neg_clobber_flags): Similarly. (addsi3_clobber_flags): Similarly. Update last argument to output_plussi to distinguish when we need flags or do not need flags. (addhi3_clobber_flags): Similarly. Twiddle code for cases +-1, +-2 and +-4. * config/h8300/h8300.md: Define iterators, mode attributes and substitutions for use in compare/test elimination. * config/h8300/jumpcall.md (branch, branch_1): Use H8cc mode iterator to cover the different modes for the CC register. (branch_1_false): Likewise. gcc/testsuite * gcc.target/h8300/add.c: New test. * gcc.target/h8300/add-2.c: New test. * gcc.target/h8300/add-3.c: New test. * gcc.target/h8300/sub.c: New test. * gcc.target/h8300/sub-2.c: New test. * gcc.target/h8300/sub-3.c: New test. --- gcc/config/h8300/addsub.md | 54 +++++++---- gcc/config/h8300/h8300.md | 33 +++++++ gcc/config/h8300/jumpcall.md | 10 +-- gcc/testsuite/gcc.target/h8300/add-2.c | 5 ++ gcc/testsuite/gcc.target/h8300/add-3.c | 5 ++ gcc/testsuite/gcc.target/h8300/add.c | 118 +++++++++++++++++++++++++ gcc/testsuite/gcc.target/h8300/sub-2.c | 5 ++ gcc/testsuite/gcc.target/h8300/sub-3.c | 5 ++ gcc/testsuite/gcc.target/h8300/sub.c | 118 +++++++++++++++++++++++++ 9 files changed, 333 insertions(+), 20 deletions(-) create mode 100644 gcc/testsuite/gcc.target/h8300/add-2.c create mode 100644 gcc/testsuite/gcc.target/h8300/add-3.c create mode 100644 gcc/testsuite/gcc.target/h8300/add.c create mode 100644 gcc/testsuite/gcc.target/h8300/sub-2.c create mode 100644 gcc/testsuite/gcc.target/h8300/sub-3.c create mode 100644 gcc/testsuite/gcc.target/h8300/sub.c diff --git a/gcc/config/h8300/addsub.md b/gcc/config/h8300/addsub.md index d0877c008bf0..3585bffa9fc5 100644 --- a/gcc/config/h8300/addsub.md +++ b/gcc/config/h8300/addsub.md @@ -19,7 +19,7 @@ [(parallel [(set (match_dup 0) (plus:QI (match_dup 1) (match_dup 2))) (clobber (reg:CC CC_REG))])]) -(define_insn "*addqi3_clobber_flags" +(define_insn "*addqi3_flags" [(set (match_operand:QI 0 "h8300_dst_operand" "=rQ") (plus:QI (match_operand:QI 1 "h8300_dst_operand" "%0") (match_operand:QI 2 "h8300_src_operand" "rQi"))) @@ -38,18 +38,41 @@ [(parallel [(set (match_dup 0) (plus:HI (match_dup 1) (match_dup 2))) (clobber (reg:CC CC_REG))])]) -(define_insn "*addhi3_clobber_flags" +(define_insn "*addhi3_flags" [(set (match_operand:HI 0 "register_operand" "=r,r,r,r,r") (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,0,0") - (match_operand:HI 2 "h8300_src_operand" "L,N,J,n,r"))) + (match_operand:HI 2 "h8300_src_operand" "M,O,J,n,r"))) (clobber (reg:CC CC_REG))] "reload_completed && !TARGET_H8300SX" - "@ - adds %2,%S0 - subs %G2,%S0 - add.b %t2,%t0 - add.w %T2,%T0 - add.w %T2,%T0" + "* + { + switch (which_alternative) + { + case 0: + return \"inc %T2,%T0\"; + case 1: + return \"dec %G2,%T0\"; + case 2: + return \"add.b %t2,%t0\"; + case 3: + { + /* If the constant is 4 or -4 and we do not need the + flags, then we can use adds/subs which is two bytes + shorter. */ + rtx x = XVECEXP (PATTERN (insn), 0, 1); + bool clobber = GET_CODE (x) == CLOBBER; + if (clobber && INTVAL (operands[2]) == 4) + return \"adds %2,%S0\"; + if (clobber && INTVAL (operands[2]) == -4) + return \"subs %G2,%S0\"; + return \"add.w %T2,%T0\"; + } + case 4: + return \"add.w %T2,%T0\"; + default: + gcc_unreachable (); + } + }" [(set_attr "length" "2,2,2,4,2")]) (define_insn_and_split "*addhi3_h8sx" @@ -62,7 +85,7 @@ [(parallel [(set (match_dup 0) (plus:HI (match_dup 1) (match_dup 2))) (clobber (reg:CC CC_REG))])]) -(define_insn "*addhi3_h8sx_clobber_flags" +(define_insn "*addhi3_h8sx_flags" [(set (match_operand:HI 0 "h8300_dst_operand" "=rU,rU,r,rQ") (plus:HI (match_operand:HI 1 "h8300_dst_operand" "%0,0,0,0") (match_operand:HI 2 "h8300_src_operand" "P3>X,P3" [(set (match_operand:SI 0 "h8300_dst_operand" "=rQ,rQ") (plus:SI (match_operand:SI 1 "h8300_dst_operand" "%0,0") (match_operand:SI 2 "h8300_src_operand" "i,rQ"))) (clobber (reg:CC CC_REG))] "reload_completed && h8300_operands_match_p (operands)" { - return output_plussi (operands, false); + rtx x = XVECEXP (PATTERN (insn), 0, 1); + return output_plussi (operands, GET_CODE (x) != CLOBBER); } [(set (attr "length") (symbol_ref "compute_plussi_length (operands, false)"))]) @@ -130,7 +154,7 @@ [(parallel [(set (match_dup 0) (minus:QI (match_dup 1) (match_dup 2))) (clobber (reg:CC CC_REG))])]) -(define_insn "*subqi3_clobber_flags" +(define_insn "*subqi3_flags" [(set (match_operand:QI 0 "h8300_dst_operand" "=rQ") (minus:QI (match_operand:QI 1 "h8300_dst_operand" "0") (match_operand:QI 2 "h8300_dst_operand" "rQ"))) @@ -149,7 +173,7 @@ [(parallel [(set (match_dup 0) (minus:HSI (match_dup 1) (match_dup 2))) (clobber (reg:CC CC_REG))])]) -(define_insn "*sub3_clobber_flags" +(define_insn "*sub3_flags" [(set (match_operand:HSI 0 "h8300_dst_operand" "=rQ,rQ") (minus:HSI (match_operand:HSI 1 "h8300_dst_operand" "0,0") (match_operand:HSI 2 "h8300_src_operand" "rQ,i"))) @@ -183,7 +207,7 @@ [(parallel [(set (match_dup 0) (neg:QHSI (match_dup 1))) (clobber (reg:CC CC_REG))])]) -(define_insn "*neg2_clobber_flags" +(define_insn "*neg2_flags" [(set (match_operand:QHSI 0 "h8300_dst_operand" "=rQ") (neg:QHSI (match_operand:QHSI 1 "h8300_dst_operand" "0"))) (clobber (reg:CC CC_REG))] diff --git a/gcc/config/h8300/h8300.md b/gcc/config/h8300/h8300.md index 7c9cc324f39e..932f74eb88fe 100644 --- a/gcc/config/h8300/h8300.md +++ b/gcc/config/h8300/h8300.md @@ -134,6 +134,39 @@ (define_attr "old_cc" "none,none_0hit,set_znv,set_zn,compare,clobber" (const_string "clobber")) +;; So the idea here is to define iterators and substitutions so that we +;; can easily modify the patterns with CC clobbers into a pattern +;; which sets appropriate condition codes + +;; The modes we're supporting. This is used when we want to generate +;; multiple patterns where only the mode differs from a single template +(define_mode_iterator H8cc [CC CCZN]) + +;; This is used to generate multiple define_substs from a single +;; template for the different variants we might have. +(define_mode_attr cc [(CC "cc") (CCZN "cczn")]) + +;; The primary substitution pattern. is used to create multiple +;; substitutions based on the CC bits that are set. +;; +;; The mode iterator sets the actual mode on the condition code +;; REG expression. +(define_subst "subst_" + [(set (match_operand 0 "") + (match_operand 1 "")) + (clobber (reg:CC CC_REG))] + "" + [(set (reg:H8cc CC_REG) + (compare:H8cc (match_dup 1) (const_int 0))) + (set (match_dup 0) (match_dup 1))]) + + +;; So when we see or in a define_insn pattern, we'll +;; apply the subst_cczn or subset_cc define_subst to generate a +;; new pattern that compare-elim can use +(define_subst_attr "cczn" "subst_cczn" "" "_cczn") +(define_subst_attr "cc" "subst_cc" "" "_cc") + ;; Type of delay slot. NONE means the instruction has no delay slot. ;; JUMP means it is an unconditional jump that (if short enough) ;; could be implemented using bra/s. diff --git a/gcc/config/h8300/jumpcall.md b/gcc/config/h8300/jumpcall.md index c07dbaf999c1..49d1e4312ca1 100644 --- a/gcc/config/h8300/jumpcall.md +++ b/gcc/config/h8300/jumpcall.md @@ -23,18 +23,18 @@ "" "#" "reload_completed" - [(set (reg:CC CC_REG) - (compare:CC (match_dup 1) (match_dup 2))) + [(set (reg:H8cc CC_REG) + (compare:H8cc (match_dup 1) (match_dup 2))) (set (pc) (if_then_else (match_op_dup 0 - [(reg:CC CC_REG) (const_int 0)]) + [(reg:H8cc CC_REG) (const_int 0)]) (label_ref (match_dup 3)) (pc)))] "") (define_insn "*branch_1" [(set (pc) (if_then_else (match_operator 1 "comparison_operator" - [(reg:CC CC_REG) (const_int 0)]) + [(reg:H8cc CC_REG) (const_int 0)]) (label_ref (match_operand 0 "" "")) (pc)))] "reload_completed" @@ -52,7 +52,7 @@ (define_insn "*branch_1_false" [(set (pc) (if_then_else (match_operator 1 "comparison_operator" - [(reg:CC CC_REG) (const_int 0)]) + [(reg:H8cc CC_REG) (const_int 0)]) (pc) (label_ref (match_operand 0 "" ""))))] "reload_completed" diff --git a/gcc/testsuite/gcc.target/h8300/add-2.c b/gcc/testsuite/gcc.target/h8300/add-2.c new file mode 100644 index 000000000000..27f9b2f00695 --- /dev/null +++ b/gcc/testsuite/gcc.target/h8300/add-2.c @@ -0,0 +1,5 @@ +/* { dg-do compile } */ +/* { dg-options "-ms -mint32 -O2" } */ +/* { dg-final { scan-assembler-not "cmp" } } */ + +#include "add.c" diff --git a/gcc/testsuite/gcc.target/h8300/add-3.c b/gcc/testsuite/gcc.target/h8300/add-3.c new file mode 100644 index 000000000000..20de647c9449 --- /dev/null +++ b/gcc/testsuite/gcc.target/h8300/add-3.c @@ -0,0 +1,5 @@ +/* { dg-do compile } */ +/* { dg-options "-msx -mint32 -O2" } */ +/* { dg-final { scan-assembler-not "cmp" } } */ + +#include "add.c" diff --git a/gcc/testsuite/gcc.target/h8300/add.c b/gcc/testsuite/gcc.target/h8300/add.c new file mode 100644 index 000000000000..ebeea579f6b1 --- /dev/null +++ b/gcc/testsuite/gcc.target/h8300/add.c @@ -0,0 +1,118 @@ +/* { dg-do compile } */ +/* { dg-options "-mh -mint32 -O2" } */ +/* { dg-final { scan-assembler-not "cmp" } } */ + +typedef unsigned char uchar; +typedef signed char schar; +typedef unsigned short ushort; +typedef unsigned long ulong; + +volatile void abort (void); + + +#define ADD(T)\ +T addE##T (T x, T y) { T t = x + y ; if (t == 0) abort (); return t; } \ +T addNE##T (T x, T y) { T t = x + y ; if (t != 0) return t; abort (); } \ +T addGE##T (T x, T y) { T t = x + y ; if (t >= 0) abort (); return t; } \ +T addLT##T (T x, T y) { T t = x + y ; if (t < 0) abort (); return t; } + +#define ADDC(T,N)\ +T addEQ##N##T (T a) { T t = a + N; if (t == 0) abort (); return t; } \ +T addNE##N##T (T a) { T t = a + N; if (t != 0) return t; abort (); } \ +T addGE##N##T (T a) { T t = a + N; if (t >= 0) abort (); return t; } \ +T addLT##N##T (T a) { T t = a + N; if (t < 0) abort (); return t; } + +#define ADDNC(T,N)\ +T addEQN##N##T (T a) { T t = a + -N; if (t == 0) abort (); return t; } \ +T addNEN##N##T (T a) { T t = a + -N; if (t != 0) return t; abort (); } \ +T addGEN##N##T (T a) { T t = a + -N; if (t >= 0) abort (); return t; } \ +T addLTN##N##T (T a) { T t = a + -N; if (t < 0) abort (); return t; } + + +ADD (schar) +ADD (short) +ADD (long) +ADD (uchar) +ADD (ushort) +ADD (ulong) + + + +ADDC (schar,1) +ADDC (schar,2) +ADDC (schar,3) +ADDC (schar,4) +ADDC (schar,6) +ADDC (schar,8) +ADDNC (schar,1) +ADDNC (schar,2) +ADDNC (schar,3) +ADDNC (schar,4) +ADDNC (schar,6) +ADDNC (schar,8) + +ADDC (uchar,1) +ADDC (uchar,2) +ADDC (uchar,3) +ADDC (uchar,4) +ADDC (uchar,6) +ADDC (uchar,8) +ADDNC (uchar,1) +ADDNC (uchar,2) +ADDNC (uchar,3) +ADDNC (uchar,4) +ADDNC (uchar,6) +ADDNC (uchar,8) + +ADDC (short,1) +ADDC (short,2) +ADDC (short,3) +ADDC (short,4) +ADDC (short,6) +ADDC (short,8) +ADDNC (short,1) +ADDNC (short,2) +ADDNC (short,3) +ADDNC (short,4) +ADDNC (short,6) +ADDNC (short,8) + +ADDC (ushort,1) +ADDC (ushort,2) +ADDC (ushort,3) +ADDC (ushort,4) +ADDC (ushort,6) +ADDC (ushort,8) +ADDNC (ushort,1) +ADDNC (ushort,2) +ADDNC (ushort,3) +ADDNC (ushort,4) +ADDNC (ushort,6) +ADDNC (ushort,8) + +ADDC (long,1) +ADDC (long,2) +ADDC (long,3) +ADDC (long,4) +ADDC (long,6) +ADDC (long,8) +ADDNC (long,1) +ADDNC (long,2) +ADDNC (long,3) +ADDNC (long,4) +ADDNC (long,6) +ADDNC (long,8) + +ADDC (ulong,1) +ADDC (ulong,2) +ADDC (ulong,3) +ADDC (ulong,4) +ADDC (ulong,6) +ADDC (ulong,8) +ADDNC (ulong,1) +ADDNC (ulong,2) +ADDNC (ulong,3) +ADDNC (ulong,4) +ADDNC (ulong,6) +ADDNC (ulong,8) + diff --git a/gcc/testsuite/gcc.target/h8300/sub-2.c b/gcc/testsuite/gcc.target/h8300/sub-2.c new file mode 100644 index 000000000000..c2914bd1d975 --- /dev/null +++ b/gcc/testsuite/gcc.target/h8300/sub-2.c @@ -0,0 +1,5 @@ +/* { dg-do compile } */ +/* { dg-options "-ms -mint32 -O2" } */ +/* { dg-final { scan-assembler-not "cmp" } } */ + +#include "sub.c" diff --git a/gcc/testsuite/gcc.target/h8300/sub-3.c b/gcc/testsuite/gcc.target/h8300/sub-3.c new file mode 100644 index 000000000000..72bcf04d1563 --- /dev/null +++ b/gcc/testsuite/gcc.target/h8300/sub-3.c @@ -0,0 +1,5 @@ +/* { dg-do compile } */ +/* { dg-options "-msx -mint32 -O2" } */ +/* { dg-final { scan-assembler-not "cmp" } } */ + +#include "sub.c" diff --git a/gcc/testsuite/gcc.target/h8300/sub.c b/gcc/testsuite/gcc.target/h8300/sub.c new file mode 100644 index 000000000000..66b63ab447df --- /dev/null +++ b/gcc/testsuite/gcc.target/h8300/sub.c @@ -0,0 +1,118 @@ +/* { dg-do compile } */ +/* { dg-options "-mh -mint32 -O2" } */ +/* { dg-final { scan-assembler-not "cmp" } } */ + +typedef unsigned char uchar; +typedef signed char schar; +typedef unsigned short ushort; +typedef unsigned long ulong; + +volatile void abort (void); + + +#define SUB(T)\ +T subE##T (T x, T y) { T t = x - y ; if (t == 0) abort (); return t; } \ +T subNE##T (T x, T y) { T t = x - y ; if (t != 0) return t; abort (); } \ +T subGE##T (T x, T y) { T t = x - y ; if (t >= 0) abort (); return t; } \ +T subLT##T (T x, T y) { T t = x - y ; if (t < 0) abort (); return t; } + +#define SUBC(T,N)\ +T subEQ##N##T (T a) { T t = a - N; if (t == 0) abort (); return t; } \ +T subNE##N##T (T a) { T t = a - N; if (t != 0) return t; abort (); } \ +T subGE##N##T (T a) { T t = a - N; if (t >= 0) abort (); return t; } \ +T subLT##N##T (T a) { T t = a - N; if (t < 0) abort (); return t; } + +#define SUBNC(T,N)\ +T subEQN##N##T (T a) { T t = a - -N; if (t == 0) abort (); return t; } \ +T subNEN##N##T (T a) { T t = a - -N; if (t != 0) return t; abort (); } \ +T subGEN##N##T (T a) { T t = a - -N; if (t >= 0) abort (); return t; } \ +T subLTN##N##T (T a) { T t = a - -N; if (t < 0) abort (); return t; } + + +SUB (schar) +SUB (short) +SUB (long) +SUB (uchar) +SUB (ushort) +SUB (ulong) + + + +SUBC (schar,1) +SUBC (schar,2) +SUBC (schar,3) +SUBC (schar,4) +SUBC (schar,6) +SUBC (schar,8) +SUBNC (schar,1) +SUBNC (schar,2) +SUBNC (schar,3) +SUBNC (schar,4) +SUBNC (schar,6) +SUBNC (schar,8) + +SUBC (uchar,1) +SUBC (uchar,2) +SUBC (uchar,3) +SUBC (uchar,4) +SUBC (uchar,6) +SUBC (uchar,8) +SUBNC (uchar,1) +SUBNC (uchar,2) +SUBNC (uchar,3) +SUBNC (uchar,4) +SUBNC (uchar,6) +SUBNC (uchar,8) + +SUBC (short,1) +SUBC (short,2) +SUBC (short,3) +SUBC (short,4) +SUBC (short,6) +SUBC (short,8) +SUBNC (short,1) +SUBNC (short,2) +SUBNC (short,3) +SUBNC (short,4) +SUBNC (short,6) +SUBNC (short,8) + +SUBC (ushort,1) +SUBC (ushort,2) +SUBC (ushort,3) +SUBC (ushort,4) +SUBC (ushort,6) +SUBC (ushort,8) +SUBNC (ushort,1) +SUBNC (ushort,2) +SUBNC (ushort,3) +SUBNC (ushort,4) +SUBNC (ushort,6) +SUBNC (ushort,8) + +SUBC (long,1) +SUBC (long,2) +SUBC (long,3) +SUBC (long,4) +SUBC (long,6) +SUBC (long,8) +SUBNC (long,1) +SUBNC (long,2) +SUBNC (long,3) +SUBNC (long,4) +SUBNC (long,6) +SUBNC (long,8) + +SUBC (ulong,1) +SUBC (ulong,2) +SUBC (ulong,3) +SUBC (ulong,4) +SUBC (ulong,6) +SUBC (ulong,8) +SUBNC (ulong,1) +SUBNC (ulong,2) +SUBNC (ulong,3) +SUBNC (ulong,4) +SUBNC (ulong,6) +SUBNC (ulong,8) + -- 2.47.2