Support limited setcc for H8
authorJeff Law <jlaw@localhost.localdomain>
Fri, 27 Aug 2021 21:01:37 +0000 (17:01 -0400)
committerJeff Law <jlaw@localhost.localdomain>
Fri, 27 Aug 2021 21:01:37 +0000 (17:01 -0400)
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

gcc/config/h8300/bitfield.md
gcc/config/h8300/h8300-protos.h
gcc/config/h8300/h8300.c
gcc/config/h8300/h8300.md
gcc/config/h8300/testcompare.md

index 82cb161..0d28c75 100644 (file)
 }
   [(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)]))]
index 3d34401..4a9624f 100644 (file)
@@ -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);
index 5f7251a..a63c322 100644 (file)
@@ -3256,30 +3256,8 @@ compute_logical_op_length (machine_mode mode, rtx_code code, rtx *operands, rtx_
   return length;
 }
 
-\f
 #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));
-}
-
-
+\f
 /* Expand a conditional store.  */
 
 void
index 7f49e42..89bfcf1 100644 (file)
 (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")])
+
 \f
 (include "movepush.md")
 (include "mova.md")
index 2919053..9ff7a51 100644 (file)
   "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")
   [(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)))])