diff options
author | Jeff Law <jlaw@localhost.localdomain> | 2021-08-27 17:01:37 -0400 |
---|---|---|
committer | Jeff Law <jlaw@localhost.localdomain> | 2021-08-27 17:01:37 -0400 |
commit | ee914ec4f811243ad72aceea4748687c74f38bc6 (patch) | |
tree | 828b93a8960fe4c65aa95aae24652c2b82bbd2ba | |
parent | 10c834f976c349970ee4b8eb3b4fce140972f256 (diff) | |
download | gcc-ee914ec4f811243ad72aceea4748687c74f38bc6.zip gcc-ee914ec4f811243ad72aceea4748687c74f38bc6.tar.gz gcc-ee914ec4f811243ad72aceea4748687c74f38bc6.tar.bz2 |
Support limited setcc for H8
gcc/
* config/h8300/bitfield.md (cstore<mode>4): Remove expander.
* config/h8300/h8300.c (h8300_expand_branch): Remove function.
* config/h8300/h8300-protos.h (h8300_expadn_branch): Remove prototype.
* config/h8300/h8300.md (eqne): New code iterator.
(geultu, geultu_to_c): Similarly.
* config/h8300/testcompare.md (cstore<mode>4): Dummy expander.
(store_c_<mode>, store_c_i_<mode>): New define_insn_and_splits
(cmp<mode>_c): New pattern
-rw-r--r-- | gcc/config/h8300/bitfield.md | 11 | ||||
-rw-r--r-- | gcc/config/h8300/h8300-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/h8300/h8300.c | 24 | ||||
-rw-r--r-- | gcc/config/h8300/h8300.md | 8 | ||||
-rw-r--r-- | gcc/config/h8300/testcompare.md | 80 |
5 files changed, 89 insertions, 35 deletions
diff --git a/gcc/config/h8300/bitfield.md b/gcc/config/h8300/bitfield.md index 82cb161..0d28c75 100644 --- a/gcc/config/h8300/bitfield.md +++ b/gcc/config/h8300/bitfield.md @@ -338,17 +338,6 @@ } [(set_attr "length_table" "bitfield")]) -;;(define_expand "cstore<mode>4" -;; [(use (match_operator 1 "eqne_operator" -;; [(match_operand:QHSI 2 "h8300_dst_operand" "") -;; (match_operand:QHSI 3 "h8300_src_operand" "")])) -;; (clobber (match_operand:QHSI 0 "register_operand"))] -;; "TARGET_H8300SX" -;; { -;; h8300_expand_store (operands); -;; DONE; -;; }) - ;;(define_insn "*bstzhireg" ;; [(set (match_operand:HI 0 "register_operand" "=r") ;; (match_operator:HI 1 "eqne_operator" [(cc0) (const_int 0)]))] diff --git a/gcc/config/h8300/h8300-protos.h b/gcc/config/h8300/h8300-protos.h index 3d34401..4a9624f 100644 --- a/gcc/config/h8300/h8300-protos.h +++ b/gcc/config/h8300/h8300-protos.h @@ -45,7 +45,6 @@ extern int compute_a_shift_cc (rtx *, rtx_code); #ifdef HAVE_ATTR_cc extern enum attr_cc compute_plussi_cc (rtx *); #endif -extern void h8300_expand_branch (rtx[]); extern void h8300_expand_store (rtx[]); extern bool expand_a_shift (machine_mode, enum rtx_code, rtx[]); extern int h8300_shift_needs_scratch_p (int, machine_mode, rtx_code); diff --git a/gcc/config/h8300/h8300.c b/gcc/config/h8300/h8300.c index 5f7251a..a63c322 100644 --- a/gcc/config/h8300/h8300.c +++ b/gcc/config/h8300/h8300.c @@ -3256,30 +3256,8 @@ compute_logical_op_length (machine_mode mode, rtx_code code, rtx *operands, rtx_ return length; } - #if 0 -/* Expand a conditional branch. */ - -void -h8300_expand_branch (rtx operands[]) -{ - enum rtx_code code = GET_CODE (operands[0]); - rtx op0 = operands[1]; - rtx op1 = operands[2]; - rtx label = operands[3]; - rtx tmp; - - tmp = gen_rtx_COMPARE (VOIDmode, op0, op1); - emit_insn (gen_rtx_SET (cc0_rtx, tmp)); - - tmp = gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx); - tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp, - gen_rtx_LABEL_REF (VOIDmode, label), - pc_rtx); - emit_jump_insn (gen_rtx_SET (pc_rtx, tmp)); -} - - + /* Expand a conditional store. */ void diff --git a/gcc/config/h8300/h8300.md b/gcc/config/h8300/h8300.md index 7f49e42..89bfcf1 100644 --- a/gcc/config/h8300/h8300.md +++ b/gcc/config/h8300/h8300.md @@ -233,6 +233,14 @@ (define_code_iterator logicals [ior xor and]) (define_code_iterator ors [ior xor]) + +(define_code_iterator eqne [eq ne]) + +;; For storing the C flag, map from the unsigned comparison to the right +;; code for testing the C bit. +(define_code_iterator geultu [geu ltu]) +(define_code_attr geultu_to_c [(geu "eq") (ltu "ne")]) + (include "movepush.md") (include "mova.md") diff --git a/gcc/config/h8300/testcompare.md b/gcc/config/h8300/testcompare.md index 2919053..9ff7a51 100644 --- a/gcc/config/h8300/testcompare.md +++ b/gcc/config/h8300/testcompare.md @@ -70,6 +70,22 @@ "mov.w %e0,%e0" [(set_attr "length" "2")]) +(define_insn "*cmp<mode>_c" + [(set (reg:CCC CC_REG) + (ltu (match_operand:QHSI 0 "h8300_dst_operand" "rQ") + (match_operand:QHSI 1 "h8300_src_operand" "rQi")))] + "reload_completed" + { + if (<MODE>mode == QImode) + return "cmp.b %X1,%X0"; + else if (<MODE>mode == HImode) + return "cmp.w %T1,%T0"; + else if (<MODE>mode == SImode) + return "cmp.l %S1,%S0"; + gcc_unreachable (); + } + [(set_attr "length_table" "add")]) + (define_insn "*cmpqi" [(set (reg:CC CC_REG) (compare (match_operand:QI 0 "h8300_dst_operand" "rQ") @@ -144,3 +160,67 @@ [(parallel [(set (reg:CCZN CC_REG) (compare:CCZN (match_dup 1) (const_int 0))) (set (match_dup 0) (match_dup 1))])]) +;; This exists solely to convince ifcvt to try some store-flag sequences. +;; +;; Essentially we don't want to expose a general store-flag capability. +;; The only generally useful/profitable case is when we want to test the +;; C bit. In that case we can use addx, subx, bst, or bist to get the bit +;; into a GPR. +;; +;; Others could be handled with stc, shifts and masking, but it likely isn't +;; profitable. +;; +(define_expand "cstore<mode>4" + [(use (match_operator 1 "eqne_operator" + [(match_operand:QHSI 2 "h8300_dst_operand" "") + (match_operand:QHSI 3 "h8300_src_operand" "")])) + (clobber (match_operand:QHSI 0 "register_operand"))] + "" + { + FAIL; + }) + +;; Storing the C bit is pretty simple since there are many ways to +;; introduce it into a GPR. addx, subx and a variety of bit manipulation +;; instructions +;; +(define_insn "*store_c_<mode>" + [(set (match_operand:QHSI 0 "register_operand" "=r") + (eqne:QHSI (reg:CCC CC_REG) (const_int 0)))] + "reload_completed" + { + if (<CODE> == NE) + { + if (<MODE>mode == QImode) + return "xor.b\t%X0,%X0\;bst\t#0,%X0"; + else if (<MODE>mode == HImode) + return "xor.w\t%T0,%T0\;bst\t#0,%s0"; + else if (<MODE>mode == SImode) + return "xor.l\t%S0,%S0\;bst\t#0,%w0"; + gcc_unreachable (); + } + else if (<CODE> == EQ) + { + if (<MODE>mode == QImode) + return "xor.b\t%X0,%X0\;bist\t#0,%X0"; + else if (<MODE>mode == HImode) + return "xor.w\t%T0,%T0\;bist\t#0,%s0"; + else if (<MODE>mode == SImode) + return "xor.l\t%S0,%S0\;bist\t#0,%w0"; + gcc_unreachable (); + } + } + [(set (attr "length") (symbol_ref "<MODE>mode == SImode ? 6 : 4"))]) + +;; Recognize this scc and generate code we can match +(define_insn_and_split "*store_c_i_<mode>" + [(set (match_operand:QHSI 0 "register_operand" "=r") + (geultu:QHSI (match_operand:QHSI 1 "register_operand" "r") + (match_operand:QHSI 2 "register_operand" "r")))] + "" + "#" + "&& reload_completed" + [(set (reg:CCC CC_REG) + (ltu:CCC (match_dup 1) (match_dup 2))) + (set (match_dup 0) + (<geultu_to_c>:QHSI (reg:CCC CC_REG) (const_int 0)))]) |