aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/h8300
diff options
context:
space:
mode:
authorJeff Law <law@redhat.com>2020-12-01 21:48:10 -0700
committerJeff Law <law@redhat.com>2020-12-01 21:49:10 -0700
commit7da97411b048cdd4e7941b311514f46ea53fe3a2 (patch)
tree62818d588b21f5445743e65ffb0a1e456389912f /gcc/config/h8300
parent4bdf1e53a8111312639b3a2f140bae4206f3a8aa (diff)
downloadgcc-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/config/h8300')
-rw-r--r--gcc/config/h8300/addsub.md54
-rw-r--r--gcc/config/h8300/h8300.md33
-rw-r--r--gcc/config/h8300/jumpcall.md10
3 files changed, 77 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"