diff options
author | Jeff Law <law@redhat.com> | 2020-12-01 21:48:10 -0700 |
---|---|---|
committer | Jeff Law <law@redhat.com> | 2020-12-01 21:49:10 -0700 |
commit | 7da97411b048cdd4e7941b311514f46ea53fe3a2 (patch) | |
tree | 62818d588b21f5445743e65ffb0a1e456389912f /gcc | |
parent | 4bdf1e53a8111312639b3a2f140bae4206f3a8aa (diff) | |
download | gcc-7da97411b048cdd4e7941b311514f46ea53fe3a2.zip gcc-7da97411b048cdd4e7941b311514f46ea53fe3a2.tar.gz gcc-7da97411b048cdd4e7941b311514f46ea53fe3a2.tar.bz2 |
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 <cczn> for define_subst.
(addhi3_h8sx_clobber_flags): Likewise.
(subqi3_clobber_flags, sub<mode>3_clobber_flags): Likewise.
(neg<mode2>_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.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/config/h8300/addsub.md | 54 | ||||
-rw-r--r-- | gcc/config/h8300/h8300.md | 33 | ||||
-rw-r--r-- | gcc/config/h8300/jumpcall.md | 10 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/h8300/add-2.c | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/h8300/add-3.c | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/h8300/add.c | 118 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/h8300/sub-2.c | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/h8300/sub-3.c | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/h8300/sub.c | 118 |
9 files changed, 333 insertions, 20 deletions
diff --git a/gcc/config/h8300/addsub.md b/gcc/config/h8300/addsub.md index d0877c0..3585bff 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<cczn>" [(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<cczn>" [(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<cczn>" [(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<X,J,rQi"))) @@ -98,14 +121,15 @@ [(parallel [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2))) (clobber (reg:CC CC_REG))])]) -(define_insn "*addsi_clobber_flags" +(define_insn "*addsi_flags<cczn>" [(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<cczn>" [(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 "*sub<mode>3_clobber_flags" +(define_insn "*sub<mode>3_flags<cczn>" [(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 "*neg<mode>2_clobber_flags" +(define_insn "*neg<mode>2_flags<cczn>" [(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 7c9cc32..932f74e 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. <cc> 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_<cc>" + [(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 <cc> or <cczn> 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 c07dbaf9..49d1e43 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 0000000..27f9b2f --- /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 0000000..20de647 --- /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 0000000..ebeea57 --- /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 0000000..c2914bd --- /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 0000000..72bcf04 --- /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 0000000..66b63ab --- /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) + |