From 3d5945610646adb6946a3251f4953929966fed2e Mon Sep 17 00:00:00 2001
From: dj <dj@138bc75d-0d04-0410-961f-82ee72b054a4>
Date: Sat, 2 Sep 2006 02:38:20 +0000
Subject: [PATCH] * config/m32c/cond.md (cbranch<mode>4): Defer splitting until
 after reload. (stzx_16): Likewise. ("stzx_24_<mode>"): Likewise.
 ("stzx_reversed_<mode>"): Likewise, and make mode-specific. ("cmp<mode>_op"):
 New. (cmp<mode>): Change to expander; just save operands. (b<code>_op): New.
 (b<code>): Change to expander, emit compare here. (s<code>_op): Change to use
 split and expander. (s<code>_24_op): Likewise. (s<code>_<mode>): New.
 (s<code>_<mode>_24): New. (movqicc_<code>_<mode): New.
 (movhicc_<code>_<mode>): New. (s<code>): New. (s<code>_24): New. *
 config/m32c/m32c.c (compare_op0, compare_op1): New. (m32c_pend_compare): New.
 (m32c_unpend_compare): New. (m32c_expand_scc): New. (m32c_expand_movcc): Emit
 the compare also. * config/m32c/predicates.md (mra_nopp_operand): New.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@116653 138bc75d-0d04-0410-961f-82ee72b054a4
---
 gcc/ChangeLog                 |  25 ++++++
 gcc/config/m32c/cond.md       | 161 ++++++++++++++++++++++++++++++----
 gcc/config/m32c/m32c-protos.h |   3 +
 gcc/config/m32c/m32c.c        |  55 ++++++++++--
 gcc/config/m32c/predicates.md |  11 +++
 5 files changed, 233 insertions(+), 22 deletions(-)

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 077b1c32a53d..2478b45d2136 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,28 @@
+2006-09-01  DJ Delorie  <dj@redhat.com>
+
+	* config/m32c/cond.md (cbranch<mode>4): Defer splitting until after reload.
+	(stzx_16): Likewise.
+	("stzx_24_<mode>"): Likewise.
+	("stzx_reversed_<mode>"): Likewise, and make mode-specific.
+	("cmp<mode>_op"): New.
+	(cmp<mode>): Change to expander; just save operands.
+	(b<code>_op): New.
+	(b<code>): Change to expander, emit compare here.
+	(s<code>_op): Change to use split and expander.
+	(s<code>_24_op): Likewise.
+	(s<code>_<mode>): New.
+	(s<code>_<mode>_24): New.
+	(movqicc_<code>_<mode): New.
+	(movhicc_<code>_<mode>): New.
+	(s<code>): New.
+	(s<code>_24): New.
+	* config/m32c/m32c.c (compare_op0, compare_op1): New.
+	(m32c_pend_compare): New.
+	(m32c_unpend_compare): New.
+	(m32c_expand_scc): New.
+	(m32c_expand_movcc): Emit the compare also.
+	* config/m32c/predicates.md (mra_nopp_operand): New.
+
 2006-09-01  J"orn Rennecke  <joern.rennecke@st.com>
 	Richard Guenther  <rguenther@suse.de>
 	Adam Nemet  <anemet@caviumnetworks.com>
diff --git a/gcc/config/m32c/cond.md b/gcc/config/m32c/cond.md
index 9df4d041409c..be590afc49e2 100644
--- a/gcc/config/m32c/cond.md
+++ b/gcc/config/m32c/cond.md
@@ -22,6 +22,20 @@
 
 ; conditionals - cmp, jcc, setcc, etc.
 
+; Special note about conditional instructions: GCC always emits the
+; compare right before the insn, which is good, because m32c's mov
+; insns modify the flags.  However, this means that any conditional
+; insn that may require reloading must be kept with its compare until
+; after reload finishes, else the reload insns might clobber the
+; flags.  Thus, these rules:
+;
+; * the cmp* expanders just save the operands in compare_op0 and
+;   compare_op1 via m32c_pend_compare.
+; * conditional insns that won't need reload can call
+;   m32c_unpend_compare before their expansion.
+; * other insns must expand to include the compare operands within,
+;   then split after reload to a separate compare and conditional.
+
 ; Until support for relaxing is supported in gas, we must assume that
 ; short labels won't reach, so we must use long labels.
 ; Unfortunately, there aren't any conditional jumps with long labels,
@@ -41,7 +55,7 @@
 	      (pc)))]
   ""
   "#"
-  ""
+  "reload_completed"
   [(set (reg:CC FLG_REGNO)
 	(compare (match_dup 1)
 		 (match_dup 2)))
@@ -56,7 +70,7 @@
 	(if_then_else:QI (eq (reg:CC FLG_REGNO) (const_int 0))
 			 (match_operand:QI 1 "const_int_operand" "i,i,0")
 			 (match_operand:QI 2 "const_int_operand" "i,0,i")))]
-  "TARGET_A16"
+  "TARGET_A16 && reload_completed"
   "@
    stzx\t%1,%2,%0
    stz\t%1,%0
@@ -69,30 +83,30 @@
 	(if_then_else:QHI (eq (reg:CC FLG_REGNO) (const_int 0))
 			 (match_operand:QHI 1 "const_int_operand" "i,i,0")
 			 (match_operand:QHI 2 "const_int_operand" "i,0,i")))]
-  "TARGET_A24"
+  "TARGET_A24 && reload_completed"
   "@
    stzx.<bwl>\t%1,%2,%0
    stz.<bwl>\t%1,%0
    stnz.<bwl>\t%2,%0"
   [(set_attr "flags" "n,n,n")])
 
-(define_insn_and_split "stzx_reversed"
-  [(set (match_operand 0 "m32c_r0_operand" "")
-	(if_then_else (ne (reg:CC FLG_REGNO) (const_int 0))
-			 (match_operand 1 "const_int_operand" "")
-			 (match_operand 2 "const_int_operand" "")))]
-  "TARGET_A24 || GET_MODE (operands[0]) == QImode"
+(define_insn_and_split "stzx_reversed_<mode>"
+  [(set (match_operand:QHI 0 "m32c_r0_operand" "")
+	(if_then_else:QHI (ne (reg:CC FLG_REGNO) (const_int 0))
+			 (match_operand:QHI 1 "const_int_operand" "")
+			 (match_operand:QHI 2 "const_int_operand" "")))]
+  "(TARGET_A24 || GET_MODE (operands[0]) == QImode) && reload_completed"
   "#"
   ""
   [(set (match_dup 0)
-	(if_then_else (eq (reg:CC FLG_REGNO) (const_int 0))
+	(if_then_else:QHI (eq (reg:CC FLG_REGNO) (const_int 0))
 		      (match_dup 2)
 		      (match_dup 1)))]
   ""
   )
 
 
-(define_insn "cmp<mode>"
+(define_insn "cmp<mode>_op"
   [(set (reg:CC FLG_REGNO)
 	(compare (match_operand:QHPSI 0 "mra_operand" "RraSd")
 		 (match_operand:QHPSI 1 "mrai_operand" "RraSdi")))]
@@ -100,7 +114,14 @@
   "* return m32c_output_compare(insn, operands); "
   [(set_attr "flags" "oszc")])
 
-(define_insn "b<code>"
+(define_expand "cmp<mode>"
+  [(set (reg:CC FLG_REGNO)
+	(compare (match_operand:QHPSI 0 "mra_operand" "RraSd")
+		 (match_operand:QHPSI 1 "mrai_operand" "RraSdi")))]
+  ""
+  "m32c_pend_compare (operands); DONE;")
+
+(define_insn "b<code>_op"
   [(set (pc)
         (if_then_else (any_cond (reg:CC FLG_REGNO)
 				(const_int 0))
@@ -111,23 +132,131 @@
   [(set_attr "flags" "n")]
 )
 
+(define_expand "b<code>"
+  [(set (pc)
+        (if_then_else (any_cond (reg:CC FLG_REGNO)
+				(const_int 0))
+                      (label_ref (match_operand 0 ""))
+                      (pc)))]
+  ""
+  "m32c_unpend_compare ();"
+)
+
 ;; m32c_conditional_register_usage changes the setcc_gen_code array to
 ;; point to the _24 variants if needed.
 
-(define_insn "s<code>"
+;; We need to keep the compare and conditional sets together through
+;; reload, because reload might need to add address reloads to the
+;; set, which would clobber the flags.  By keeping them together, the
+;; reloads get put before the compare, thus preserving the flags.
+
+;; These are the post-split patterns for the conditional sets.
+
+(define_insn "s<code>_op"
   [(set (match_operand:QI 0 "register_operand" "=Rqi")
 	(any_cond:QI (reg:CC FLG_REGNO) (const_int 0)))]
-  "TARGET_A16"
+  "TARGET_A16 && reload_completed"
   "* return m32c_scc_pattern(operands, <CODE>);")
 
-(define_insn "s<code>_24"
+(define_insn "s<code>_24_op"
   [(set (match_operand:HI 0 "mra_operand" "=RhiSd")
 	(any_cond:HI (reg:CC FLG_REGNO) (const_int 0)))]
-  "TARGET_A24"
+  "TARGET_A24 && reload_completed"
   "sc<code>\t%0"
   [(set_attr "flags" "n")]
 )
 
+;; These are the pre-split patterns for the conditional sets.  Yes,
+;; there are a lot of permutations.
+
+(define_insn_and_split "s<code>_<mode>"
+  [(set (match_operand:QI 0 "register_operand" "=Rqi")
+	(any_cond:QI (match_operand:QHPSI 1 "mra_operand" "RraSd")
+		     (match_operand:QHPSI 2 "mrai_operand" "RraSdi")))]
+  "TARGET_A16"
+  "#"
+  "reload_completed"
+  [(set (reg:CC FLG_REGNO)
+	(compare (match_dup 1)
+		 (match_dup 2)))
+   (set (match_dup 0)
+	(any_cond:QI (reg:CC FLG_REGNO) (const_int 0)))]
+  ""
+  [(set_attr "flags" "x")]
+)
+
+(define_insn_and_split "s<code>_<mode>_24"
+  [(set (match_operand:HI 0 "mra_nopp_operand" "=RhiSd")
+	(any_cond:HI (match_operand:QHPSI 1 "mra_operand" "RraSd")
+		     (match_operand:QHPSI 2 "mrai_operand" "RraSdi")))]
+  "TARGET_A24"
+  "#"
+  "reload_completed"
+  [(set (reg:CC FLG_REGNO)
+	(compare (match_dup 1)
+		 (match_dup 2)))
+   (set (match_dup 0)
+	(any_cond:HI (reg:CC FLG_REGNO) (const_int 0)))]
+  ""
+  [(set_attr "flags" "x")]
+)
+
+(define_insn_and_split "movqicc_<code>_<mode>"
+  [(set (match_operand:QI 0 "register_operand" "")
+        (if_then_else:QI (eqne_cond:QI (match_operand:QHPSI 1 "mra_operand" "RraSd")
+				       (match_operand:QHPSI 2 "mrai_operand" "RraSdi"))
+			  (match_operand:QI 3 "const_int_operand" "")
+			  (match_operand:QI 4 "const_int_operand" "")))]
+  ""
+  "#"
+  "reload_completed"
+  [(set (reg:CC FLG_REGNO)
+	(compare (match_dup 1)
+		 (match_dup 2)))
+   (set (match_dup 0)
+        (if_then_else:QI (eqne_cond:QI (reg:CC FLG_REGNO) (const_int 0))
+			 (match_dup 3)
+			 (match_dup 4)))]
+  ""
+  [(set_attr "flags" "x")]
+  )
+
+(define_insn_and_split "movhicc_<code>_<mode>"
+  [(set (match_operand:HI 0 "register_operand" "")
+        (if_then_else:HI (eqne_cond:HI (match_operand:QHPSI 1 "mra_operand" "RraSd")
+				       (match_operand:QHPSI 2 "mrai_operand" "RraSdi"))
+			  (match_operand:QI 3 "const_int_operand" "")
+			  (match_operand:QI 4 "const_int_operand" "")))]
+  "TARGET_A24"
+  "#"
+  "reload_completed"
+  [(set (reg:CC FLG_REGNO)
+	(compare (match_dup 1)
+		 (match_dup 2)))
+   (set (match_dup 0)
+        (if_then_else:HI (eqne_cond:HI (reg:CC FLG_REGNO) (const_int 0))
+			 (match_dup 3)
+			 (match_dup 4)))]
+  ""
+  [(set_attr "flags" "x")]
+  )
+
+;; And these are the expanders, which read the pending compare
+;; operands to build a combined insn.
+
+(define_expand "s<code>"
+  [(set (match_operand:QI 0 "register_operand" "=Rqi")
+	(any_cond:QI (reg:CC FLG_REGNO) (const_int 0)))]
+  "TARGET_A16"
+  "m32c_expand_scc (<CODE>, operands); DONE;")
+
+(define_expand "s<code>_24"
+  [(set (match_operand:HI 0 "mra_nopp_operand" "=RhiSd")
+	(any_cond:HI (reg:CC FLG_REGNO) (const_int 0)))]
+  "TARGET_A24"
+  "m32c_expand_scc (<CODE>, operands); DONE;")
+
+
 (define_expand "movqicc"
   [(set (match_operand:QI 0 "register_operand" "")
         (if_then_else:QI (match_operand 1 "m32c_eqne_operator" "")
diff --git a/gcc/config/m32c/m32c-protos.h b/gcc/config/m32c/m32c-protos.h
index 6979da278a24..06bd0070ac33 100644
--- a/gcc/config/m32c/m32c-protos.h
+++ b/gcc/config/m32c/m32c-protos.h
@@ -46,6 +46,7 @@ void m32c_register_pragmas (void);
 int  m32c_regno_ok_for_base_p (int);
 int  m32c_trampoline_alignment (void);
 int  m32c_trampoline_size (void);
+void m32c_unpend_compare (void);
 
 #if defined(RTX_CODE) && defined(TREE_CODE)
 
@@ -68,6 +69,7 @@ int  m32c_expand_movmemhi (rtx *);
 int  m32c_expand_movstr (rtx *);
 void m32c_expand_neg_mulpsi3 (rtx *);
 int  m32c_expand_setmemhi (rtx *);
+void m32c_expand_scc (int, rtx *);
 int  m32c_extra_constraint_p (rtx, char, const char *);
 int  m32c_extra_constraint_p2 (rtx, char, const char *);
 int  m32c_hard_regno_nregs (int, MM);
@@ -86,6 +88,7 @@ int  m32c_mode_dependent_address (rtx);
 int  m32c_modes_tieable_p (MM, MM);
 bool m32c_mov_ok (rtx *, MM);
 char * m32c_output_compare (rtx, rtx *);
+void m32c_pend_compare (rtx *);
 int  m32c_preferred_output_reload_class (rtx, int);
 int  m32c_preferred_reload_class (rtx, int);
 int  m32c_prepare_move (rtx *, MM);
diff --git a/gcc/config/m32c/m32c.c b/gcc/config/m32c/m32c.c
index 4c2219e23d80..684678739760 100644
--- a/gcc/config/m32c/m32c.c
+++ b/gcc/config/m32c/m32c.c
@@ -3488,6 +3488,42 @@ m32c_expand_neg_mulpsi3 (rtx * operands)
   emit_insn (gen_truncsipsi2 (operands[0], temp2));
 }
 
+static rtx compare_op0, compare_op1;
+
+void
+m32c_pend_compare (rtx *operands)
+{
+  compare_op0 = operands[0];
+  compare_op1 = operands[1];
+}
+
+void
+m32c_unpend_compare (void)
+{
+  switch (GET_MODE (compare_op0))
+    {
+    case QImode:
+      emit_insn (gen_cmpqi_op (compare_op0, compare_op1));
+    case HImode:
+      emit_insn (gen_cmphi_op (compare_op0, compare_op1));
+    case PSImode:
+      emit_insn (gen_cmppsi_op (compare_op0, compare_op1));
+    }
+}
+
+void
+m32c_expand_scc (int code, rtx *operands)
+{
+  enum machine_mode mode = TARGET_A16 ? QImode : HImode;
+
+  emit_insn (gen_rtx_SET (mode,
+			  operands[0],
+			  gen_rtx_fmt_ee (code,
+					  mode,
+					  compare_op0,
+					  compare_op1)));
+}
+
 /* Pattern Output Functions */
 
 /* Returns a (OP (reg:CC FLG_REGNO) (const_int 0)) from some other
@@ -3505,6 +3541,8 @@ int
 m32c_expand_movcc (rtx *operands)
 {
   rtx rel = operands[1];
+  rtx cmp;
+
   if (GET_CODE (rel) != EQ && GET_CODE (rel) != NE)
     return 1;
   if (GET_CODE (operands[2]) != CONST_INT
@@ -3517,12 +3555,17 @@ m32c_expand_movcc (rtx *operands)
       operands[2] = operands[3];
       operands[3] = tmp;
     }
-  if (TARGET_A16)
-    emit_insn (gen_stzx_16 (operands[0], operands[2], operands[3]));
-  else if (GET_MODE (operands[0]) == QImode)
-    emit_insn (gen_stzx_24_qi (operands[0], operands[2], operands[3]));
-  else
-    emit_insn (gen_stzx_24_hi (operands[0], operands[2], operands[3]));
+
+  cmp = gen_rtx_fmt_ee (GET_CODE (rel),
+			GET_MODE (rel),
+			compare_op0,
+			compare_op1);
+
+  emit_move_insn (operands[0],
+		  gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]),
+					cmp,
+					operands[2],
+					operands[3]));
   return 0;
 }
 
diff --git a/gcc/config/m32c/predicates.md b/gcc/config/m32c/predicates.md
index 5b9549c6f7b9..b0fbc846c89d 100644
--- a/gcc/config/m32c/predicates.md
+++ b/gcc/config/m32c/predicates.md
@@ -141,6 +141,17 @@
   (and (match_operand 0 "nonimmediate_operand" "")
        (not (match_operand 1 "cr_operand" ""))))
 
+; As above, but no push/pop operations
+(define_predicate "mra_nopp_operand"
+  (match_operand 0 "mra_operand" "")
+{
+  if (GET_CODE (op) == MEM
+      && (GET_CODE (XEXP (op, 0)) == PRE_DEC
+	  || (GET_CODE (XEXP (op, 0)) == POST_INC)))
+    return 0;
+  return 1;
+})
+
 ; TRUE for memory, r0..r3, a0..a1, or immediates.
 (define_predicate "mrai_operand"
   (and (and (match_operand 0 "m32c_any_operand" "")
-- 
GitLab